From 90d8aa00456c5d9976b142e26a85b6d0881906fa Mon Sep 17 00:00:00 2001 From: Dareum Nam Date: Thu, 25 May 2023 22:49:18 -0600 Subject: [PATCH 01/26] convert to eFuel & replace select_case_vars to switch statement 1 --- src/EnergyPlus/PollutionModule.cc | 3611 +++++++++++++++-------------- src/EnergyPlus/PollutionModule.hh | 3 +- 2 files changed, 1816 insertions(+), 1798 deletions(-) diff --git a/src/EnergyPlus/PollutionModule.cc b/src/EnergyPlus/PollutionModule.cc index 554361bc026..0a01fb717a3 100644 --- a/src/EnergyPlus/PollutionModule.cc +++ b/src/EnergyPlus/PollutionModule.cc @@ -50,6 +50,7 @@ // EnergyPlus Headers #include #include +#include #include #include #include @@ -275,1804 +276,1820 @@ void GetPollutionFactorInput(EnergyPlusData &state) state.dataIPShortCut->cAlphaFieldNames, state.dataIPShortCut->cNumericFieldNames); - FuelType.FuelTypeNames(Loop) = state.dataIPShortCut->cAlphaArgs(1); + FuelType.FuelTypeNames(Loop) = static_cast( + getEnumerationValue(Constant::eFuelNamesUC, UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(1)))); - { - std::string const &SELECT_CASE_var = FuelType.FuelTypeNames(Loop); - if (SELECT_CASE_var == "NATURALGAS") { - if (Pollution.NatGasCoef.FuelFactorUsed) { - ShowWarningError( - state, format("{}: {} already entered. Previous entry will be used.", cCurrentModuleObject, FuelType.FuelTypeNames(Loop))); - continue; - } - Pollution.NatGasCoef.FuelFactorUsed = true; - // Natural Gas Coeffs - Pollution.NatGasCoef.Source = state.dataIPShortCut->rNumericArgs(1); - if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "NaturalGas", - state.dataIPShortCut->cAlphaFieldNames(2), - state.dataIPShortCut->cAlphaArgs(2), - Pollution.NatGasCoef.SourceSched, - ErrorsFound); - } - Pollution.NatGasCoef.CO2 = state.dataIPShortCut->rNumericArgs(2); - if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "NaturalGas", - state.dataIPShortCut->cAlphaFieldNames(3), - state.dataIPShortCut->cAlphaArgs(3), - Pollution.NatGasCoef.CO2Sched, - ErrorsFound); - } - Pollution.NatGasCoef.CO = state.dataIPShortCut->rNumericArgs(3); - if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "NaturalGas", - state.dataIPShortCut->cAlphaFieldNames(4), - state.dataIPShortCut->cAlphaArgs(4), - Pollution.NatGasCoef.COSched, - ErrorsFound); - } - Pollution.NatGasCoef.CH4 = state.dataIPShortCut->rNumericArgs(4); - if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "NaturalGas", - state.dataIPShortCut->cAlphaFieldNames(5), - state.dataIPShortCut->cAlphaArgs(5), - Pollution.NatGasCoef.CH4Sched, - ErrorsFound); - } - Pollution.NatGasCoef.NOx = state.dataIPShortCut->rNumericArgs(5); - if (!state.dataIPShortCut->lAlphaFieldBlanks(6)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "NaturalGas", - state.dataIPShortCut->cAlphaFieldNames(6), - state.dataIPShortCut->cAlphaArgs(6), - Pollution.NatGasCoef.NOxSched, - ErrorsFound); - } - Pollution.NatGasCoef.N2O = state.dataIPShortCut->rNumericArgs(6); - if (!state.dataIPShortCut->lAlphaFieldBlanks(7)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "NaturalGas", - state.dataIPShortCut->cAlphaFieldNames(7), - state.dataIPShortCut->cAlphaArgs(7), - Pollution.NatGasCoef.N2OSched, - ErrorsFound); - } - Pollution.NatGasCoef.SO2 = state.dataIPShortCut->rNumericArgs(7); - if (!state.dataIPShortCut->lAlphaFieldBlanks(8)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "NaturalGas", - state.dataIPShortCut->cAlphaFieldNames(8), - state.dataIPShortCut->cAlphaArgs(8), - Pollution.NatGasCoef.SO2Sched, - ErrorsFound); - } - Pollution.NatGasCoef.PM = state.dataIPShortCut->rNumericArgs(8); - if (!state.dataIPShortCut->lAlphaFieldBlanks(9)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "NaturalGas", - state.dataIPShortCut->cAlphaFieldNames(9), - state.dataIPShortCut->cAlphaArgs(9), - Pollution.NatGasCoef.PMSched, - ErrorsFound); - } - Pollution.NatGasCoef.PM10 = state.dataIPShortCut->rNumericArgs(9); - if (!state.dataIPShortCut->lAlphaFieldBlanks(10)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "NaturalGas", - state.dataIPShortCut->cAlphaFieldNames(10), - state.dataIPShortCut->cAlphaArgs(10), - Pollution.NatGasCoef.PM10Sched, - ErrorsFound); - } - Pollution.NatGasCoef.PM25 = state.dataIPShortCut->rNumericArgs(10); - if (!state.dataIPShortCut->lAlphaFieldBlanks(11)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "NaturalGas", - state.dataIPShortCut->cAlphaFieldNames(11), - state.dataIPShortCut->cAlphaArgs(11), - Pollution.NatGasCoef.PM25Sched, - ErrorsFound); - } - Pollution.NatGasCoef.NH3 = state.dataIPShortCut->rNumericArgs(11); - if (!state.dataIPShortCut->lAlphaFieldBlanks(12)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "NaturalGas", - state.dataIPShortCut->cAlphaFieldNames(12), - state.dataIPShortCut->cAlphaArgs(12), - Pollution.NatGasCoef.NH3Sched, - ErrorsFound); - } - Pollution.NatGasCoef.NMVOC = state.dataIPShortCut->rNumericArgs(12); - if (!state.dataIPShortCut->lAlphaFieldBlanks(13)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "NaturalGas", - state.dataIPShortCut->cAlphaFieldNames(13), - state.dataIPShortCut->cAlphaArgs(13), - Pollution.NatGasCoef.NMVOCSched, - ErrorsFound); - } - Pollution.NatGasCoef.Hg = state.dataIPShortCut->rNumericArgs(13); - if (!state.dataIPShortCut->lAlphaFieldBlanks(14)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "NaturalGas", - state.dataIPShortCut->cAlphaFieldNames(14), - state.dataIPShortCut->cAlphaArgs(14), - Pollution.NatGasCoef.HgSched, - ErrorsFound); - } - Pollution.NatGasCoef.Pb = state.dataIPShortCut->rNumericArgs(14); - if (!state.dataIPShortCut->lAlphaFieldBlanks(15)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "NaturalGas", - state.dataIPShortCut->cAlphaFieldNames(15), - state.dataIPShortCut->cAlphaArgs(15), - Pollution.NatGasCoef.PbSched, - ErrorsFound); - } - Pollution.NatGasCoef.Water = state.dataIPShortCut->rNumericArgs(15); - if (!state.dataIPShortCut->lAlphaFieldBlanks(16)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "NaturalGas", - state.dataIPShortCut->cAlphaFieldNames(16), - state.dataIPShortCut->cAlphaArgs(16), - Pollution.NatGasCoef.WaterSched, - ErrorsFound); - } - Pollution.NatGasCoef.NucHi = state.dataIPShortCut->rNumericArgs(16); - if (!state.dataIPShortCut->lAlphaFieldBlanks(17)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "NaturalGas", - state.dataIPShortCut->cAlphaFieldNames(17), - state.dataIPShortCut->cAlphaArgs(17), - Pollution.NatGasCoef.NucHiSched, - ErrorsFound); - } - Pollution.NatGasCoef.NucLo = state.dataIPShortCut->rNumericArgs(17); - if (!state.dataIPShortCut->lAlphaFieldBlanks(18)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "NaturalGas", - state.dataIPShortCut->cAlphaFieldNames(18), - state.dataIPShortCut->cAlphaArgs(18), - Pollution.NatGasCoef.NucLoSched, - ErrorsFound); - } - - } else if (SELECT_CASE_var == "FUELOILNO2") { - if (Pollution.FuelOil2Coef.FuelFactorUsed) { - ShowWarningError( - state, format("{}: {} already entered. Previous entry will be used.", cCurrentModuleObject, FuelType.FuelTypeNames(Loop))); - continue; - } - Pollution.FuelOil2Coef.FuelFactorUsed = true; - // FuelOilNo2 Coeffs - Pollution.FuelOil2Coef.Source = state.dataIPShortCut->rNumericArgs(1); - if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#2", - state.dataIPShortCut->cAlphaFieldNames(2), - state.dataIPShortCut->cAlphaArgs(2), - Pollution.FuelOil2Coef.SourceSched, - ErrorsFound); - } - Pollution.FuelOil2Coef.CO2 = state.dataIPShortCut->rNumericArgs(2); - if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#2", - state.dataIPShortCut->cAlphaFieldNames(3), - state.dataIPShortCut->cAlphaArgs(3), - Pollution.FuelOil2Coef.CO2Sched, - ErrorsFound); - } - Pollution.FuelOil2Coef.CO = state.dataIPShortCut->rNumericArgs(3); - if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#2", - state.dataIPShortCut->cAlphaFieldNames(4), - state.dataIPShortCut->cAlphaArgs(4), - Pollution.FuelOil2Coef.COSched, - ErrorsFound); - } - Pollution.FuelOil2Coef.CH4 = state.dataIPShortCut->rNumericArgs(4); - if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#2", - state.dataIPShortCut->cAlphaFieldNames(5), - state.dataIPShortCut->cAlphaArgs(5), - Pollution.FuelOil2Coef.CH4Sched, - ErrorsFound); - } - Pollution.FuelOil2Coef.NOx = state.dataIPShortCut->rNumericArgs(5); - if (!state.dataIPShortCut->lAlphaFieldBlanks(6)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#2", - state.dataIPShortCut->cAlphaFieldNames(6), - state.dataIPShortCut->cAlphaArgs(6), - Pollution.FuelOil2Coef.NOxSched, - ErrorsFound); - } - Pollution.FuelOil2Coef.N2O = state.dataIPShortCut->rNumericArgs(6); - if (!state.dataIPShortCut->lAlphaFieldBlanks(7)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#2", - state.dataIPShortCut->cAlphaFieldNames(7), - state.dataIPShortCut->cAlphaArgs(7), - Pollution.FuelOil2Coef.N2OSched, - ErrorsFound); - } - Pollution.FuelOil2Coef.SO2 = state.dataIPShortCut->rNumericArgs(7); - if (!state.dataIPShortCut->lAlphaFieldBlanks(8)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#2", - state.dataIPShortCut->cAlphaFieldNames(8), - state.dataIPShortCut->cAlphaArgs(8), - Pollution.FuelOil2Coef.SO2Sched, - ErrorsFound); - } - Pollution.FuelOil2Coef.PM = state.dataIPShortCut->rNumericArgs(8); - if (!state.dataIPShortCut->lAlphaFieldBlanks(9)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#2", - state.dataIPShortCut->cAlphaFieldNames(9), - state.dataIPShortCut->cAlphaArgs(9), - Pollution.FuelOil2Coef.PMSched, - ErrorsFound); - } - Pollution.FuelOil2Coef.PM10 = state.dataIPShortCut->rNumericArgs(9); - if (!state.dataIPShortCut->lAlphaFieldBlanks(10)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#2", - state.dataIPShortCut->cAlphaFieldNames(10), - state.dataIPShortCut->cAlphaArgs(10), - Pollution.FuelOil2Coef.PM10Sched, - ErrorsFound); - } - Pollution.FuelOil2Coef.PM25 = state.dataIPShortCut->rNumericArgs(10); - if (!state.dataIPShortCut->lAlphaFieldBlanks(11)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#2", - state.dataIPShortCut->cAlphaFieldNames(11), - state.dataIPShortCut->cAlphaArgs(11), - Pollution.FuelOil2Coef.PM25Sched, - ErrorsFound); - } - Pollution.FuelOil2Coef.NH3 = state.dataIPShortCut->rNumericArgs(11); - if (!state.dataIPShortCut->lAlphaFieldBlanks(12)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#2", - state.dataIPShortCut->cAlphaFieldNames(12), - state.dataIPShortCut->cAlphaArgs(12), - Pollution.FuelOil2Coef.NH3Sched, - ErrorsFound); - } - Pollution.FuelOil2Coef.NMVOC = state.dataIPShortCut->rNumericArgs(12); - if (!state.dataIPShortCut->lAlphaFieldBlanks(13)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#2", - state.dataIPShortCut->cAlphaFieldNames(13), - state.dataIPShortCut->cAlphaArgs(13), - Pollution.FuelOil2Coef.NMVOCSched, - ErrorsFound); - } - Pollution.FuelOil2Coef.Hg = state.dataIPShortCut->rNumericArgs(13); - if (!state.dataIPShortCut->lAlphaFieldBlanks(14)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#2", - state.dataIPShortCut->cAlphaFieldNames(14), - state.dataIPShortCut->cAlphaArgs(14), - Pollution.FuelOil2Coef.HgSched, - ErrorsFound); - } - Pollution.FuelOil2Coef.Pb = state.dataIPShortCut->rNumericArgs(14); - if (!state.dataIPShortCut->lAlphaFieldBlanks(15)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#2", - state.dataIPShortCut->cAlphaFieldNames(15), - state.dataIPShortCut->cAlphaArgs(15), - Pollution.FuelOil2Coef.PbSched, - ErrorsFound); - } - Pollution.FuelOil2Coef.Water = state.dataIPShortCut->rNumericArgs(15); - if (!state.dataIPShortCut->lAlphaFieldBlanks(16)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#2", - state.dataIPShortCut->cAlphaFieldNames(16), - state.dataIPShortCut->cAlphaArgs(16), - Pollution.FuelOil2Coef.WaterSched, - ErrorsFound); - } - Pollution.FuelOil2Coef.NucHi = state.dataIPShortCut->rNumericArgs(16); - if (!state.dataIPShortCut->lAlphaFieldBlanks(17)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#2", - state.dataIPShortCut->cAlphaFieldNames(17), - state.dataIPShortCut->cAlphaArgs(17), - Pollution.FuelOil2Coef.NucHiSched, - ErrorsFound); - } - Pollution.FuelOil2Coef.NucLo = state.dataIPShortCut->rNumericArgs(17); - if (!state.dataIPShortCut->lAlphaFieldBlanks(18)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#2", - state.dataIPShortCut->cAlphaFieldNames(18), - state.dataIPShortCut->cAlphaArgs(18), - Pollution.FuelOil2Coef.NucLoSched, - ErrorsFound); - } - - } else if (SELECT_CASE_var == "FUELOILNO1") { - if (Pollution.FuelOil1Coef.FuelFactorUsed) { - ShowWarningError( - state, format("{}: {} already entered. Previous entry will be used.", cCurrentModuleObject, FuelType.FuelTypeNames(Loop))); - continue; - } - Pollution.FuelOil1Coef.FuelFactorUsed = true; - // FuelOilNo1 Coeffs - Pollution.FuelOil1Coef.Source = state.dataIPShortCut->rNumericArgs(1); - if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#1", - state.dataIPShortCut->cAlphaFieldNames(2), - state.dataIPShortCut->cAlphaArgs(2), - Pollution.FuelOil1Coef.SourceSched, - ErrorsFound); - } - Pollution.FuelOil1Coef.CO2 = state.dataIPShortCut->rNumericArgs(2); - if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#1", - state.dataIPShortCut->cAlphaFieldNames(3), - state.dataIPShortCut->cAlphaArgs(3), - Pollution.FuelOil1Coef.CO2Sched, - ErrorsFound); - } - Pollution.FuelOil1Coef.CO = state.dataIPShortCut->rNumericArgs(3); - if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#1", - state.dataIPShortCut->cAlphaFieldNames(4), - state.dataIPShortCut->cAlphaArgs(4), - Pollution.FuelOil1Coef.COSched, - ErrorsFound); - } - Pollution.FuelOil1Coef.CH4 = state.dataIPShortCut->rNumericArgs(4); - if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#1", - state.dataIPShortCut->cAlphaFieldNames(5), - state.dataIPShortCut->cAlphaArgs(5), - Pollution.FuelOil1Coef.CH4Sched, - ErrorsFound); - } - Pollution.FuelOil1Coef.NOx = state.dataIPShortCut->rNumericArgs(5); - if (!state.dataIPShortCut->lAlphaFieldBlanks(6)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#1", - state.dataIPShortCut->cAlphaFieldNames(6), - state.dataIPShortCut->cAlphaArgs(6), - Pollution.FuelOil1Coef.NOxSched, - ErrorsFound); - } - Pollution.FuelOil1Coef.N2O = state.dataIPShortCut->rNumericArgs(6); - if (!state.dataIPShortCut->lAlphaFieldBlanks(7)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#1", - state.dataIPShortCut->cAlphaFieldNames(7), - state.dataIPShortCut->cAlphaArgs(7), - Pollution.FuelOil1Coef.N2OSched, - ErrorsFound); - } - Pollution.FuelOil1Coef.SO2 = state.dataIPShortCut->rNumericArgs(7); - if (!state.dataIPShortCut->lAlphaFieldBlanks(8)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#1", - state.dataIPShortCut->cAlphaFieldNames(8), - state.dataIPShortCut->cAlphaArgs(8), - Pollution.FuelOil1Coef.SO2Sched, - ErrorsFound); - } - Pollution.FuelOil1Coef.PM = state.dataIPShortCut->rNumericArgs(8); - if (!state.dataIPShortCut->lAlphaFieldBlanks(9)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#1", - state.dataIPShortCut->cAlphaFieldNames(9), - state.dataIPShortCut->cAlphaArgs(9), - Pollution.FuelOil1Coef.PMSched, - ErrorsFound); - } - Pollution.FuelOil1Coef.PM10 = state.dataIPShortCut->rNumericArgs(9); - if (!state.dataIPShortCut->lAlphaFieldBlanks(10)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#1", - state.dataIPShortCut->cAlphaFieldNames(10), - state.dataIPShortCut->cAlphaArgs(10), - Pollution.FuelOil1Coef.PM10Sched, - ErrorsFound); - } - Pollution.FuelOil1Coef.PM25 = state.dataIPShortCut->rNumericArgs(10); - if (!state.dataIPShortCut->lAlphaFieldBlanks(11)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#1", - state.dataIPShortCut->cAlphaFieldNames(11), - state.dataIPShortCut->cAlphaArgs(11), - Pollution.FuelOil1Coef.PM25Sched, - ErrorsFound); - } - Pollution.FuelOil1Coef.NH3 = state.dataIPShortCut->rNumericArgs(11); - if (!state.dataIPShortCut->lAlphaFieldBlanks(12)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#1", - state.dataIPShortCut->cAlphaFieldNames(12), - state.dataIPShortCut->cAlphaArgs(12), - Pollution.FuelOil1Coef.NH3Sched, - ErrorsFound); - } - Pollution.FuelOil1Coef.NMVOC = state.dataIPShortCut->rNumericArgs(12); - if (!state.dataIPShortCut->lAlphaFieldBlanks(13)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#1", - state.dataIPShortCut->cAlphaFieldNames(13), - state.dataIPShortCut->cAlphaArgs(13), - Pollution.FuelOil1Coef.NMVOCSched, - ErrorsFound); - } - Pollution.FuelOil1Coef.Hg = state.dataIPShortCut->rNumericArgs(13); - if (!state.dataIPShortCut->lAlphaFieldBlanks(14)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#1", - state.dataIPShortCut->cAlphaFieldNames(14), - state.dataIPShortCut->cAlphaArgs(14), - Pollution.FuelOil1Coef.HgSched, - ErrorsFound); - } - Pollution.FuelOil1Coef.Pb = state.dataIPShortCut->rNumericArgs(14); - if (!state.dataIPShortCut->lAlphaFieldBlanks(15)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#1", - state.dataIPShortCut->cAlphaFieldNames(15), - state.dataIPShortCut->cAlphaArgs(15), - Pollution.FuelOil1Coef.PbSched, - ErrorsFound); - } - Pollution.FuelOil1Coef.Water = state.dataIPShortCut->rNumericArgs(15); - if (!state.dataIPShortCut->lAlphaFieldBlanks(16)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#1", - state.dataIPShortCut->cAlphaFieldNames(16), - state.dataIPShortCut->cAlphaArgs(16), - Pollution.FuelOil1Coef.WaterSched, - ErrorsFound); - } - Pollution.FuelOil1Coef.NucHi = state.dataIPShortCut->rNumericArgs(16); - if (!state.dataIPShortCut->lAlphaFieldBlanks(17)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#1", - state.dataIPShortCut->cAlphaFieldNames(17), - state.dataIPShortCut->cAlphaArgs(17), - Pollution.FuelOil1Coef.NucHiSched, - ErrorsFound); - } - Pollution.FuelOil1Coef.NucLo = state.dataIPShortCut->rNumericArgs(17); - if (!state.dataIPShortCut->lAlphaFieldBlanks(18)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Fuel Oil#1", - state.dataIPShortCut->cAlphaFieldNames(18), - state.dataIPShortCut->cAlphaArgs(18), - Pollution.FuelOil1Coef.NucLoSched, - ErrorsFound); - } - - } else if (SELECT_CASE_var == "COAL") { - if (Pollution.CoalCoef.FuelFactorUsed) { - ShowWarningError( - state, format("{}: {} already entered. Previous entry will be used.", cCurrentModuleObject, FuelType.FuelTypeNames(Loop))); - continue; - } - Pollution.CoalCoef.FuelFactorUsed = true; - // Coal - Pollution.CoalCoef.Source = state.dataIPShortCut->rNumericArgs(1); - if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Coal", - state.dataIPShortCut->cAlphaFieldNames(2), - state.dataIPShortCut->cAlphaArgs(2), - Pollution.CoalCoef.SourceSched, - ErrorsFound); - } - Pollution.CoalCoef.CO2 = state.dataIPShortCut->rNumericArgs(2); - if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Coal", - state.dataIPShortCut->cAlphaFieldNames(3), - state.dataIPShortCut->cAlphaArgs(3), - Pollution.CoalCoef.CO2Sched, - ErrorsFound); - } - Pollution.CoalCoef.CO = state.dataIPShortCut->rNumericArgs(3); - if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Coal", - state.dataIPShortCut->cAlphaFieldNames(4), - state.dataIPShortCut->cAlphaArgs(4), - Pollution.CoalCoef.COSched, - ErrorsFound); - } - Pollution.CoalCoef.CH4 = state.dataIPShortCut->rNumericArgs(4); - if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Coal", - state.dataIPShortCut->cAlphaFieldNames(5), - state.dataIPShortCut->cAlphaArgs(5), - Pollution.CoalCoef.CH4Sched, - ErrorsFound); - } - Pollution.CoalCoef.NOx = state.dataIPShortCut->rNumericArgs(5); - if (!state.dataIPShortCut->lAlphaFieldBlanks(6)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Coal", - state.dataIPShortCut->cAlphaFieldNames(6), - state.dataIPShortCut->cAlphaArgs(6), - Pollution.CoalCoef.NOxSched, - ErrorsFound); - } - Pollution.CoalCoef.N2O = state.dataIPShortCut->rNumericArgs(6); - if (!state.dataIPShortCut->lAlphaFieldBlanks(7)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Coal", - state.dataIPShortCut->cAlphaFieldNames(7), - state.dataIPShortCut->cAlphaArgs(7), - Pollution.CoalCoef.N2OSched, - ErrorsFound); - } - Pollution.CoalCoef.SO2 = state.dataIPShortCut->rNumericArgs(7); - if (!state.dataIPShortCut->lAlphaFieldBlanks(8)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Coal", - state.dataIPShortCut->cAlphaFieldNames(8), - state.dataIPShortCut->cAlphaArgs(8), - Pollution.CoalCoef.SO2Sched, - ErrorsFound); - } - Pollution.CoalCoef.PM = state.dataIPShortCut->rNumericArgs(8); - if (!state.dataIPShortCut->lAlphaFieldBlanks(9)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Coal", - state.dataIPShortCut->cAlphaFieldNames(9), - state.dataIPShortCut->cAlphaArgs(9), - Pollution.CoalCoef.PMSched, - ErrorsFound); - } - Pollution.CoalCoef.PM10 = state.dataIPShortCut->rNumericArgs(9); - if (!state.dataIPShortCut->lAlphaFieldBlanks(10)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Coal", - state.dataIPShortCut->cAlphaFieldNames(10), - state.dataIPShortCut->cAlphaArgs(10), - Pollution.CoalCoef.PM10Sched, - ErrorsFound); - } - Pollution.CoalCoef.PM25 = state.dataIPShortCut->rNumericArgs(10); - if (!state.dataIPShortCut->lAlphaFieldBlanks(11)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Coal", - state.dataIPShortCut->cAlphaFieldNames(11), - state.dataIPShortCut->cAlphaArgs(11), - Pollution.CoalCoef.PM25Sched, - ErrorsFound); - } - Pollution.CoalCoef.NH3 = state.dataIPShortCut->rNumericArgs(11); - if (!state.dataIPShortCut->lAlphaFieldBlanks(12)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Coal", - state.dataIPShortCut->cAlphaFieldNames(12), - state.dataIPShortCut->cAlphaArgs(12), - Pollution.CoalCoef.NH3Sched, - ErrorsFound); - } - Pollution.CoalCoef.NMVOC = state.dataIPShortCut->rNumericArgs(12); - if (!state.dataIPShortCut->lAlphaFieldBlanks(13)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Coal", - state.dataIPShortCut->cAlphaFieldNames(13), - state.dataIPShortCut->cAlphaArgs(13), - Pollution.CoalCoef.NMVOCSched, - ErrorsFound); - } - Pollution.CoalCoef.Hg = state.dataIPShortCut->rNumericArgs(13); - if (!state.dataIPShortCut->lAlphaFieldBlanks(14)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Coal", - state.dataIPShortCut->cAlphaFieldNames(14), - state.dataIPShortCut->cAlphaArgs(14), - Pollution.CoalCoef.HgSched, - ErrorsFound); - } - Pollution.CoalCoef.Pb = state.dataIPShortCut->rNumericArgs(14); - if (!state.dataIPShortCut->lAlphaFieldBlanks(15)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Coal", - state.dataIPShortCut->cAlphaFieldNames(15), - state.dataIPShortCut->cAlphaArgs(15), - Pollution.CoalCoef.PbSched, - ErrorsFound); - } - Pollution.CoalCoef.Water = state.dataIPShortCut->rNumericArgs(15); - if (!state.dataIPShortCut->lAlphaFieldBlanks(16)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Coal", - state.dataIPShortCut->cAlphaFieldNames(16), - state.dataIPShortCut->cAlphaArgs(16), - Pollution.CoalCoef.WaterSched, - ErrorsFound); - } - Pollution.CoalCoef.NucHi = state.dataIPShortCut->rNumericArgs(16); - if (!state.dataIPShortCut->lAlphaFieldBlanks(17)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Coal", - state.dataIPShortCut->cAlphaFieldNames(17), - state.dataIPShortCut->cAlphaArgs(17), - Pollution.CoalCoef.NucHiSched, - ErrorsFound); - } - Pollution.CoalCoef.NucLo = state.dataIPShortCut->rNumericArgs(17); - if (!state.dataIPShortCut->lAlphaFieldBlanks(18)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Coal", - state.dataIPShortCut->cAlphaFieldNames(18), - state.dataIPShortCut->cAlphaArgs(18), - Pollution.CoalCoef.NucLoSched, - ErrorsFound); - } - - } else if (SELECT_CASE_var == "ELECTRICITY") { - if (Pollution.ElecCoef.FuelFactorUsed) { - ShowWarningError( - state, format("{}: {} already entered. Previous entry will be used.", cCurrentModuleObject, FuelType.FuelTypeNames(Loop))); - continue; - } - Pollution.ElecCoef.FuelFactorUsed = true; - // Electric Coeffs - Pollution.ElecCoef.Source = state.dataIPShortCut->rNumericArgs(1); - if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Electricity", - state.dataIPShortCut->cAlphaFieldNames(2), - state.dataIPShortCut->cAlphaArgs(2), - Pollution.ElecCoef.SourceSched, - ErrorsFound); - } - Pollution.ElecCoef.CO2 = state.dataIPShortCut->rNumericArgs(2); - if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Electricity", - state.dataIPShortCut->cAlphaFieldNames(3), - state.dataIPShortCut->cAlphaArgs(3), - Pollution.ElecCoef.CO2Sched, - ErrorsFound); - } - Pollution.ElecCoef.CO = state.dataIPShortCut->rNumericArgs(3); - if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Electricity", - state.dataIPShortCut->cAlphaFieldNames(4), - state.dataIPShortCut->cAlphaArgs(4), - Pollution.ElecCoef.COSched, - ErrorsFound); - } - Pollution.ElecCoef.CH4 = state.dataIPShortCut->rNumericArgs(4); - if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Electricity", - state.dataIPShortCut->cAlphaFieldNames(5), - state.dataIPShortCut->cAlphaArgs(5), - Pollution.ElecCoef.CH4Sched, - ErrorsFound); - } - Pollution.ElecCoef.NOx = state.dataIPShortCut->rNumericArgs(5); - if (!state.dataIPShortCut->lAlphaFieldBlanks(6)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Electricity", - state.dataIPShortCut->cAlphaFieldNames(6), - state.dataIPShortCut->cAlphaArgs(6), - Pollution.ElecCoef.NOxSched, - ErrorsFound); - } - Pollution.ElecCoef.N2O = state.dataIPShortCut->rNumericArgs(6); - if (!state.dataIPShortCut->lAlphaFieldBlanks(7)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Electricity", - state.dataIPShortCut->cAlphaFieldNames(7), - state.dataIPShortCut->cAlphaArgs(7), - Pollution.ElecCoef.N2OSched, - ErrorsFound); - } - Pollution.ElecCoef.SO2 = state.dataIPShortCut->rNumericArgs(7); - if (!state.dataIPShortCut->lAlphaFieldBlanks(8)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Electricity", - state.dataIPShortCut->cAlphaFieldNames(8), - state.dataIPShortCut->cAlphaArgs(8), - Pollution.ElecCoef.SO2Sched, - ErrorsFound); - } - Pollution.ElecCoef.PM = state.dataIPShortCut->rNumericArgs(8); - if (!state.dataIPShortCut->lAlphaFieldBlanks(9)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Electricity", - state.dataIPShortCut->cAlphaFieldNames(9), - state.dataIPShortCut->cAlphaArgs(9), - Pollution.ElecCoef.PMSched, - ErrorsFound); - } - Pollution.ElecCoef.PM10 = state.dataIPShortCut->rNumericArgs(9); - if (!state.dataIPShortCut->lAlphaFieldBlanks(10)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Electricity", - state.dataIPShortCut->cAlphaFieldNames(10), - state.dataIPShortCut->cAlphaArgs(10), - Pollution.ElecCoef.PM10Sched, - ErrorsFound); - } - Pollution.ElecCoef.PM25 = state.dataIPShortCut->rNumericArgs(10); - if (!state.dataIPShortCut->lAlphaFieldBlanks(11)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Electricity", - state.dataIPShortCut->cAlphaFieldNames(11), - state.dataIPShortCut->cAlphaArgs(11), - Pollution.ElecCoef.PM25Sched, - ErrorsFound); - } - Pollution.ElecCoef.NH3 = state.dataIPShortCut->rNumericArgs(11); - if (!state.dataIPShortCut->lAlphaFieldBlanks(12)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Electricity", - state.dataIPShortCut->cAlphaFieldNames(12), - state.dataIPShortCut->cAlphaArgs(12), - Pollution.ElecCoef.NH3Sched, - ErrorsFound); - } - Pollution.ElecCoef.NMVOC = state.dataIPShortCut->rNumericArgs(12); - if (!state.dataIPShortCut->lAlphaFieldBlanks(13)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Electricity", - state.dataIPShortCut->cAlphaFieldNames(13), - state.dataIPShortCut->cAlphaArgs(13), - Pollution.ElecCoef.NMVOCSched, - ErrorsFound); - } - Pollution.ElecCoef.Hg = state.dataIPShortCut->rNumericArgs(13); - if (!state.dataIPShortCut->lAlphaFieldBlanks(14)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Electricity", - state.dataIPShortCut->cAlphaFieldNames(14), - state.dataIPShortCut->cAlphaArgs(14), - Pollution.ElecCoef.HgSched, - ErrorsFound); - } - Pollution.ElecCoef.Pb = state.dataIPShortCut->rNumericArgs(14); - if (!state.dataIPShortCut->lAlphaFieldBlanks(15)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Electricity", - state.dataIPShortCut->cAlphaFieldNames(15), - state.dataIPShortCut->cAlphaArgs(15), - Pollution.ElecCoef.PbSched, - ErrorsFound); - } - Pollution.ElecCoef.Water = state.dataIPShortCut->rNumericArgs(15); - if (!state.dataIPShortCut->lAlphaFieldBlanks(16)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Electricity", - state.dataIPShortCut->cAlphaFieldNames(16), - state.dataIPShortCut->cAlphaArgs(16), - Pollution.ElecCoef.WaterSched, - ErrorsFound); - } - Pollution.ElecCoef.NucHi = state.dataIPShortCut->rNumericArgs(16); - if (!state.dataIPShortCut->lAlphaFieldBlanks(17)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Electricity", - state.dataIPShortCut->cAlphaFieldNames(17), - state.dataIPShortCut->cAlphaArgs(17), - Pollution.ElecCoef.NucHiSched, - ErrorsFound); - } - Pollution.ElecCoef.NucLo = state.dataIPShortCut->rNumericArgs(17); - if (!state.dataIPShortCut->lAlphaFieldBlanks(18)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Electricity", - state.dataIPShortCut->cAlphaFieldNames(18), - state.dataIPShortCut->cAlphaArgs(18), - Pollution.ElecCoef.NucLoSched, - ErrorsFound); - } - - } else if (SELECT_CASE_var == "GASOLINE") { - if (Pollution.GasolineCoef.FuelFactorUsed) { - ShowWarningError( - state, format("{}: {} already entered. Previous entry will be used.", cCurrentModuleObject, FuelType.FuelTypeNames(Loop))); - continue; - } - Pollution.GasolineCoef.FuelFactorUsed = true; - // Gasoline Coeffs - Pollution.GasolineCoef.Source = state.dataIPShortCut->rNumericArgs(1); - if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Gasoline", - state.dataIPShortCut->cAlphaFieldNames(2), - state.dataIPShortCut->cAlphaArgs(2), - Pollution.GasolineCoef.SourceSched, - ErrorsFound); - } - Pollution.GasolineCoef.CO2 = state.dataIPShortCut->rNumericArgs(2); - if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Gasoline", - state.dataIPShortCut->cAlphaFieldNames(3), - state.dataIPShortCut->cAlphaArgs(3), - Pollution.GasolineCoef.CO2Sched, - ErrorsFound); - } - Pollution.GasolineCoef.CO = state.dataIPShortCut->rNumericArgs(3); - if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Gasoline", - state.dataIPShortCut->cAlphaFieldNames(4), - state.dataIPShortCut->cAlphaArgs(4), - Pollution.GasolineCoef.COSched, - ErrorsFound); - } - Pollution.GasolineCoef.CH4 = state.dataIPShortCut->rNumericArgs(4); - if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Gasoline", - state.dataIPShortCut->cAlphaFieldNames(5), - state.dataIPShortCut->cAlphaArgs(5), - Pollution.GasolineCoef.CH4Sched, - ErrorsFound); - } - Pollution.GasolineCoef.NOx = state.dataIPShortCut->rNumericArgs(5); - if (!state.dataIPShortCut->lAlphaFieldBlanks(6)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Gasoline", - state.dataIPShortCut->cAlphaFieldNames(6), - state.dataIPShortCut->cAlphaArgs(6), - Pollution.GasolineCoef.NOxSched, - ErrorsFound); - } - Pollution.GasolineCoef.N2O = state.dataIPShortCut->rNumericArgs(6); - if (!state.dataIPShortCut->lAlphaFieldBlanks(7)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Gasoline", - state.dataIPShortCut->cAlphaFieldNames(7), - state.dataIPShortCut->cAlphaArgs(7), - Pollution.GasolineCoef.N2OSched, - ErrorsFound); - } - Pollution.GasolineCoef.SO2 = state.dataIPShortCut->rNumericArgs(7); - if (!state.dataIPShortCut->lAlphaFieldBlanks(8)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Gasoline", - state.dataIPShortCut->cAlphaFieldNames(8), - state.dataIPShortCut->cAlphaArgs(8), - Pollution.GasolineCoef.SO2Sched, - ErrorsFound); - } - Pollution.GasolineCoef.PM = state.dataIPShortCut->rNumericArgs(8); - if (!state.dataIPShortCut->lAlphaFieldBlanks(9)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Gasoline", - state.dataIPShortCut->cAlphaFieldNames(9), - state.dataIPShortCut->cAlphaArgs(9), - Pollution.GasolineCoef.PMSched, - ErrorsFound); - } - Pollution.GasolineCoef.PM10 = state.dataIPShortCut->rNumericArgs(9); - if (!state.dataIPShortCut->lAlphaFieldBlanks(10)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Gasoline", - state.dataIPShortCut->cAlphaFieldNames(10), - state.dataIPShortCut->cAlphaArgs(10), - Pollution.GasolineCoef.PM10Sched, - ErrorsFound); - } - Pollution.GasolineCoef.PM25 = state.dataIPShortCut->rNumericArgs(10); - if (!state.dataIPShortCut->lAlphaFieldBlanks(11)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Gasoline", - state.dataIPShortCut->cAlphaFieldNames(11), - state.dataIPShortCut->cAlphaArgs(11), - Pollution.GasolineCoef.PM25Sched, - ErrorsFound); - } - Pollution.GasolineCoef.NH3 = state.dataIPShortCut->rNumericArgs(11); - if (!state.dataIPShortCut->lAlphaFieldBlanks(12)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Gasoline", - state.dataIPShortCut->cAlphaFieldNames(12), - state.dataIPShortCut->cAlphaArgs(12), - Pollution.GasolineCoef.NH3Sched, - ErrorsFound); - } - Pollution.GasolineCoef.NMVOC = state.dataIPShortCut->rNumericArgs(12); - if (!state.dataIPShortCut->lAlphaFieldBlanks(13)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Gasoline", - state.dataIPShortCut->cAlphaFieldNames(13), - state.dataIPShortCut->cAlphaArgs(13), - Pollution.GasolineCoef.NMVOCSched, - ErrorsFound); - } - Pollution.GasolineCoef.Hg = state.dataIPShortCut->rNumericArgs(13); - if (!state.dataIPShortCut->lAlphaFieldBlanks(14)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Gasoline", - state.dataIPShortCut->cAlphaFieldNames(14), - state.dataIPShortCut->cAlphaArgs(14), - Pollution.GasolineCoef.HgSched, - ErrorsFound); - } - Pollution.GasolineCoef.Pb = state.dataIPShortCut->rNumericArgs(14); - if (!state.dataIPShortCut->lAlphaFieldBlanks(15)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Gasoline", - state.dataIPShortCut->cAlphaFieldNames(15), - state.dataIPShortCut->cAlphaArgs(15), - Pollution.GasolineCoef.PbSched, - ErrorsFound); - } - Pollution.GasolineCoef.Water = state.dataIPShortCut->rNumericArgs(15); - if (!state.dataIPShortCut->lAlphaFieldBlanks(16)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Gasoline", - state.dataIPShortCut->cAlphaFieldNames(16), - state.dataIPShortCut->cAlphaArgs(16), - Pollution.GasolineCoef.WaterSched, - ErrorsFound); - } - Pollution.GasolineCoef.NucHi = state.dataIPShortCut->rNumericArgs(16); - if (!state.dataIPShortCut->lAlphaFieldBlanks(17)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Gasoline", - state.dataIPShortCut->cAlphaFieldNames(17), - state.dataIPShortCut->cAlphaArgs(17), - Pollution.GasolineCoef.NucHiSched, - ErrorsFound); - } - Pollution.GasolineCoef.NucLo = state.dataIPShortCut->rNumericArgs(17); - if (!state.dataIPShortCut->lAlphaFieldBlanks(18)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Gasoline", - state.dataIPShortCut->cAlphaFieldNames(18), - state.dataIPShortCut->cAlphaArgs(18), - Pollution.GasolineCoef.NucLoSched, - ErrorsFound); - } - - } else if (SELECT_CASE_var == "PROPANE") { - if (Pollution.PropaneCoef.FuelFactorUsed) { - ShowWarningError( - state, format("{}: {} already entered. Previous entry will be used.", cCurrentModuleObject, FuelType.FuelTypeNames(Loop))); - continue; - } - Pollution.PropaneCoef.FuelFactorUsed = true; - // Propane Coeffs - Pollution.PropaneCoef.Source = state.dataIPShortCut->rNumericArgs(1); - if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Propane", - state.dataIPShortCut->cAlphaFieldNames(2), - state.dataIPShortCut->cAlphaArgs(2), - Pollution.PropaneCoef.SourceSched, - ErrorsFound); - } - Pollution.PropaneCoef.CO2 = state.dataIPShortCut->rNumericArgs(2); - if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Propane", - state.dataIPShortCut->cAlphaFieldNames(3), - state.dataIPShortCut->cAlphaArgs(3), - Pollution.PropaneCoef.CO2Sched, - ErrorsFound); - } - Pollution.PropaneCoef.CO = state.dataIPShortCut->rNumericArgs(3); - if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Propane", - state.dataIPShortCut->cAlphaFieldNames(4), - state.dataIPShortCut->cAlphaArgs(4), - Pollution.PropaneCoef.COSched, - ErrorsFound); - } - Pollution.PropaneCoef.CH4 = state.dataIPShortCut->rNumericArgs(4); - if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Propane", - state.dataIPShortCut->cAlphaFieldNames(5), - state.dataIPShortCut->cAlphaArgs(5), - Pollution.PropaneCoef.CH4Sched, - ErrorsFound); - } - Pollution.PropaneCoef.NOx = state.dataIPShortCut->rNumericArgs(5); - if (!state.dataIPShortCut->lAlphaFieldBlanks(6)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Propane", - state.dataIPShortCut->cAlphaFieldNames(6), - state.dataIPShortCut->cAlphaArgs(6), - Pollution.PropaneCoef.NOxSched, - ErrorsFound); - } - Pollution.PropaneCoef.N2O = state.dataIPShortCut->rNumericArgs(6); - if (!state.dataIPShortCut->lAlphaFieldBlanks(7)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Propane", - state.dataIPShortCut->cAlphaFieldNames(7), - state.dataIPShortCut->cAlphaArgs(7), - Pollution.PropaneCoef.N2OSched, - ErrorsFound); - } - Pollution.PropaneCoef.SO2 = state.dataIPShortCut->rNumericArgs(7); - if (!state.dataIPShortCut->lAlphaFieldBlanks(8)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Propane", - state.dataIPShortCut->cAlphaFieldNames(8), - state.dataIPShortCut->cAlphaArgs(8), - Pollution.PropaneCoef.SO2Sched, - ErrorsFound); - } - Pollution.PropaneCoef.PM = state.dataIPShortCut->rNumericArgs(8); - if (!state.dataIPShortCut->lAlphaFieldBlanks(9)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Propane", - state.dataIPShortCut->cAlphaFieldNames(9), - state.dataIPShortCut->cAlphaArgs(9), - Pollution.PropaneCoef.PMSched, - ErrorsFound); - } - Pollution.PropaneCoef.PM10 = state.dataIPShortCut->rNumericArgs(9); - if (!state.dataIPShortCut->lAlphaFieldBlanks(10)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Propane", - state.dataIPShortCut->cAlphaFieldNames(10), - state.dataIPShortCut->cAlphaArgs(10), - Pollution.PropaneCoef.PM10Sched, - ErrorsFound); - } - Pollution.PropaneCoef.PM25 = state.dataIPShortCut->rNumericArgs(10); - if (!state.dataIPShortCut->lAlphaFieldBlanks(11)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Propane", - state.dataIPShortCut->cAlphaFieldNames(11), - state.dataIPShortCut->cAlphaArgs(11), - Pollution.PropaneCoef.PM25Sched, - ErrorsFound); - } - Pollution.PropaneCoef.NH3 = state.dataIPShortCut->rNumericArgs(11); - if (!state.dataIPShortCut->lAlphaFieldBlanks(12)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Propane", - state.dataIPShortCut->cAlphaFieldNames(12), - state.dataIPShortCut->cAlphaArgs(12), - Pollution.PropaneCoef.NH3Sched, - ErrorsFound); - } - Pollution.PropaneCoef.NMVOC = state.dataIPShortCut->rNumericArgs(12); - if (!state.dataIPShortCut->lAlphaFieldBlanks(13)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Propane", - state.dataIPShortCut->cAlphaFieldNames(13), - state.dataIPShortCut->cAlphaArgs(13), - Pollution.PropaneCoef.NMVOCSched, - ErrorsFound); - } - Pollution.PropaneCoef.Hg = state.dataIPShortCut->rNumericArgs(13); - if (!state.dataIPShortCut->lAlphaFieldBlanks(14)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Propane", - state.dataIPShortCut->cAlphaFieldNames(14), - state.dataIPShortCut->cAlphaArgs(14), - Pollution.PropaneCoef.HgSched, - ErrorsFound); - } - Pollution.PropaneCoef.Pb = state.dataIPShortCut->rNumericArgs(14); - if (!state.dataIPShortCut->lAlphaFieldBlanks(15)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Propane", - state.dataIPShortCut->cAlphaFieldNames(15), - state.dataIPShortCut->cAlphaArgs(15), - Pollution.PropaneCoef.PbSched, - ErrorsFound); - } - Pollution.PropaneCoef.Water = state.dataIPShortCut->rNumericArgs(15); - if (!state.dataIPShortCut->lAlphaFieldBlanks(16)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Propane", - state.dataIPShortCut->cAlphaFieldNames(16), - state.dataIPShortCut->cAlphaArgs(16), - Pollution.PropaneCoef.WaterSched, - ErrorsFound); - } - Pollution.PropaneCoef.NucHi = state.dataIPShortCut->rNumericArgs(16); - if (!state.dataIPShortCut->lAlphaFieldBlanks(17)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Propane", - state.dataIPShortCut->cAlphaFieldNames(17), - state.dataIPShortCut->cAlphaArgs(17), - Pollution.PropaneCoef.NucHiSched, - ErrorsFound); - } - Pollution.PropaneCoef.NucLo = state.dataIPShortCut->rNumericArgs(17); - if (!state.dataIPShortCut->lAlphaFieldBlanks(18)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Propane", - state.dataIPShortCut->cAlphaFieldNames(18), - state.dataIPShortCut->cAlphaArgs(18), - Pollution.PropaneCoef.NucLoSched, - ErrorsFound); - } - - } else if (SELECT_CASE_var == "DIESEL") { - if (Pollution.DieselCoef.FuelFactorUsed) { - ShowWarningError( - state, format("{}: {} already entered. Previous entry will be used.", cCurrentModuleObject, FuelType.FuelTypeNames(Loop))); - continue; - } - Pollution.DieselCoef.FuelFactorUsed = true; - // Diesel Coeffs - Pollution.DieselCoef.Source = state.dataIPShortCut->rNumericArgs(1); - if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Diesel", - state.dataIPShortCut->cAlphaFieldNames(2), - state.dataIPShortCut->cAlphaArgs(2), - Pollution.DieselCoef.SourceSched, - ErrorsFound); - } - Pollution.DieselCoef.CO2 = state.dataIPShortCut->rNumericArgs(2); - if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Diesel", - state.dataIPShortCut->cAlphaFieldNames(3), - state.dataIPShortCut->cAlphaArgs(3), - Pollution.DieselCoef.CO2Sched, - ErrorsFound); - } - Pollution.DieselCoef.CO = state.dataIPShortCut->rNumericArgs(3); - if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Diesel", - state.dataIPShortCut->cAlphaFieldNames(4), - state.dataIPShortCut->cAlphaArgs(4), - Pollution.DieselCoef.COSched, - ErrorsFound); - } - Pollution.DieselCoef.CH4 = state.dataIPShortCut->rNumericArgs(4); - if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Diesel", - state.dataIPShortCut->cAlphaFieldNames(5), - state.dataIPShortCut->cAlphaArgs(5), - Pollution.DieselCoef.CH4Sched, - ErrorsFound); - } - Pollution.DieselCoef.NOx = state.dataIPShortCut->rNumericArgs(5); - if (!state.dataIPShortCut->lAlphaFieldBlanks(6)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Diesel", - state.dataIPShortCut->cAlphaFieldNames(6), - state.dataIPShortCut->cAlphaArgs(6), - Pollution.DieselCoef.NOxSched, - ErrorsFound); - } - Pollution.DieselCoef.N2O = state.dataIPShortCut->rNumericArgs(6); - if (!state.dataIPShortCut->lAlphaFieldBlanks(7)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Diesel", - state.dataIPShortCut->cAlphaFieldNames(7), - state.dataIPShortCut->cAlphaArgs(7), - Pollution.DieselCoef.N2OSched, - ErrorsFound); - } - Pollution.DieselCoef.SO2 = state.dataIPShortCut->rNumericArgs(7); - if (!state.dataIPShortCut->lAlphaFieldBlanks(8)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Diesel", - state.dataIPShortCut->cAlphaFieldNames(8), - state.dataIPShortCut->cAlphaArgs(8), - Pollution.DieselCoef.SO2Sched, - ErrorsFound); - } - Pollution.DieselCoef.PM = state.dataIPShortCut->rNumericArgs(8); - if (!state.dataIPShortCut->lAlphaFieldBlanks(9)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Diesel", - state.dataIPShortCut->cAlphaFieldNames(9), - state.dataIPShortCut->cAlphaArgs(9), - Pollution.DieselCoef.PMSched, - ErrorsFound); - } - Pollution.DieselCoef.PM10 = state.dataIPShortCut->rNumericArgs(9); - if (!state.dataIPShortCut->lAlphaFieldBlanks(10)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Diesel", - state.dataIPShortCut->cAlphaFieldNames(10), - state.dataIPShortCut->cAlphaArgs(10), - Pollution.DieselCoef.PM10Sched, - ErrorsFound); - } - Pollution.DieselCoef.PM25 = state.dataIPShortCut->rNumericArgs(10); - if (!state.dataIPShortCut->lAlphaFieldBlanks(11)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Diesel", - state.dataIPShortCut->cAlphaFieldNames(11), - state.dataIPShortCut->cAlphaArgs(11), - Pollution.DieselCoef.PM25Sched, - ErrorsFound); - } - Pollution.DieselCoef.NH3 = state.dataIPShortCut->rNumericArgs(11); - if (!state.dataIPShortCut->lAlphaFieldBlanks(12)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Diesel", - state.dataIPShortCut->cAlphaFieldNames(12), - state.dataIPShortCut->cAlphaArgs(12), - Pollution.DieselCoef.NH3Sched, - ErrorsFound); - } - Pollution.DieselCoef.NMVOC = state.dataIPShortCut->rNumericArgs(12); - if (!state.dataIPShortCut->lAlphaFieldBlanks(13)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Diesel", - state.dataIPShortCut->cAlphaFieldNames(13), - state.dataIPShortCut->cAlphaArgs(13), - Pollution.DieselCoef.NMVOCSched, - ErrorsFound); - } - Pollution.DieselCoef.Hg = state.dataIPShortCut->rNumericArgs(13); - if (!state.dataIPShortCut->lAlphaFieldBlanks(14)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Diesel", - state.dataIPShortCut->cAlphaFieldNames(14), - state.dataIPShortCut->cAlphaArgs(14), - Pollution.DieselCoef.HgSched, - ErrorsFound); - } - Pollution.DieselCoef.Pb = state.dataIPShortCut->rNumericArgs(14); - if (!state.dataIPShortCut->lAlphaFieldBlanks(15)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Diesel", - state.dataIPShortCut->cAlphaFieldNames(15), - state.dataIPShortCut->cAlphaArgs(15), - Pollution.DieselCoef.PbSched, - ErrorsFound); - } - Pollution.DieselCoef.Water = state.dataIPShortCut->rNumericArgs(15); - if (!state.dataIPShortCut->lAlphaFieldBlanks(16)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Diesel", - state.dataIPShortCut->cAlphaFieldNames(16), - state.dataIPShortCut->cAlphaArgs(16), - Pollution.DieselCoef.WaterSched, - ErrorsFound); - } - Pollution.DieselCoef.NucHi = state.dataIPShortCut->rNumericArgs(16); - if (!state.dataIPShortCut->lAlphaFieldBlanks(17)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Diesel", - state.dataIPShortCut->cAlphaFieldNames(17), - state.dataIPShortCut->cAlphaArgs(17), - Pollution.DieselCoef.NucHiSched, - ErrorsFound); - } - Pollution.DieselCoef.NucLo = state.dataIPShortCut->rNumericArgs(17); - if (!state.dataIPShortCut->lAlphaFieldBlanks(18)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "Diesel", - state.dataIPShortCut->cAlphaFieldNames(18), - state.dataIPShortCut->cAlphaArgs(18), - Pollution.DieselCoef.NucLoSched, - ErrorsFound); - } - - } else if (SELECT_CASE_var == "OTHERFUEL1") { - if (Pollution.OtherFuel1Coef.FuelFactorUsed) { - ShowWarningError( - state, format("{}: {} already entered. Previous entry will be used.", cCurrentModuleObject, FuelType.FuelTypeNames(Loop))); - continue; - } - Pollution.OtherFuel1Coef.FuelFactorUsed = true; - // OtherFuel1 Coeffs - Pollution.OtherFuel1Coef.Source = state.dataIPShortCut->rNumericArgs(1); - if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel1", - state.dataIPShortCut->cAlphaFieldNames(2), - state.dataIPShortCut->cAlphaArgs(2), - Pollution.OtherFuel1Coef.SourceSched, - ErrorsFound); - } - Pollution.OtherFuel1Coef.CO2 = state.dataIPShortCut->rNumericArgs(2); - if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel1", - state.dataIPShortCut->cAlphaFieldNames(3), - state.dataIPShortCut->cAlphaArgs(3), - Pollution.OtherFuel1Coef.CO2Sched, - ErrorsFound); - } - Pollution.OtherFuel1Coef.CO = state.dataIPShortCut->rNumericArgs(3); - if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel1", - state.dataIPShortCut->cAlphaFieldNames(4), - state.dataIPShortCut->cAlphaArgs(4), - Pollution.OtherFuel1Coef.COSched, - ErrorsFound); - } - Pollution.OtherFuel1Coef.CH4 = state.dataIPShortCut->rNumericArgs(4); - if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel1", - state.dataIPShortCut->cAlphaFieldNames(5), - state.dataIPShortCut->cAlphaArgs(5), - Pollution.OtherFuel1Coef.CH4Sched, - ErrorsFound); - } - Pollution.OtherFuel1Coef.NOx = state.dataIPShortCut->rNumericArgs(5); - if (!state.dataIPShortCut->lAlphaFieldBlanks(6)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel1", - state.dataIPShortCut->cAlphaFieldNames(6), - state.dataIPShortCut->cAlphaArgs(6), - Pollution.OtherFuel1Coef.NOxSched, - ErrorsFound); - } - Pollution.OtherFuel1Coef.N2O = state.dataIPShortCut->rNumericArgs(6); - if (!state.dataIPShortCut->lAlphaFieldBlanks(7)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel1", - state.dataIPShortCut->cAlphaFieldNames(7), - state.dataIPShortCut->cAlphaArgs(7), - Pollution.OtherFuel1Coef.N2OSched, - ErrorsFound); - } - Pollution.OtherFuel1Coef.SO2 = state.dataIPShortCut->rNumericArgs(7); - if (!state.dataIPShortCut->lAlphaFieldBlanks(8)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel1", - state.dataIPShortCut->cAlphaFieldNames(8), - state.dataIPShortCut->cAlphaArgs(8), - Pollution.OtherFuel1Coef.SO2Sched, - ErrorsFound); - } - Pollution.OtherFuel1Coef.PM = state.dataIPShortCut->rNumericArgs(8); - if (!state.dataIPShortCut->lAlphaFieldBlanks(9)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel1", - state.dataIPShortCut->cAlphaFieldNames(9), - state.dataIPShortCut->cAlphaArgs(9), - Pollution.OtherFuel1Coef.PMSched, - ErrorsFound); - } - Pollution.OtherFuel1Coef.PM10 = state.dataIPShortCut->rNumericArgs(9); - if (!state.dataIPShortCut->lAlphaFieldBlanks(10)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel1", - state.dataIPShortCut->cAlphaFieldNames(10), - state.dataIPShortCut->cAlphaArgs(10), - Pollution.OtherFuel1Coef.PM10Sched, - ErrorsFound); - } - Pollution.OtherFuel1Coef.PM25 = state.dataIPShortCut->rNumericArgs(10); - if (!state.dataIPShortCut->lAlphaFieldBlanks(11)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel1", - state.dataIPShortCut->cAlphaFieldNames(11), - state.dataIPShortCut->cAlphaArgs(11), - Pollution.OtherFuel1Coef.PM25Sched, - ErrorsFound); - } - Pollution.OtherFuel1Coef.NH3 = state.dataIPShortCut->rNumericArgs(11); - if (!state.dataIPShortCut->lAlphaFieldBlanks(12)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel1", - state.dataIPShortCut->cAlphaFieldNames(12), - state.dataIPShortCut->cAlphaArgs(12), - Pollution.OtherFuel1Coef.NH3Sched, - ErrorsFound); - } - Pollution.OtherFuel1Coef.NMVOC = state.dataIPShortCut->rNumericArgs(12); - if (!state.dataIPShortCut->lAlphaFieldBlanks(13)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel1", - state.dataIPShortCut->cAlphaFieldNames(13), - state.dataIPShortCut->cAlphaArgs(13), - Pollution.OtherFuel1Coef.NMVOCSched, - ErrorsFound); - } - Pollution.OtherFuel1Coef.Hg = state.dataIPShortCut->rNumericArgs(13); - if (!state.dataIPShortCut->lAlphaFieldBlanks(14)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel1", - state.dataIPShortCut->cAlphaFieldNames(14), - state.dataIPShortCut->cAlphaArgs(14), - Pollution.OtherFuel1Coef.HgSched, - ErrorsFound); - } - Pollution.OtherFuel1Coef.Pb = state.dataIPShortCut->rNumericArgs(14); - if (!state.dataIPShortCut->lAlphaFieldBlanks(15)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel1", - state.dataIPShortCut->cAlphaFieldNames(15), - state.dataIPShortCut->cAlphaArgs(15), - Pollution.OtherFuel1Coef.PbSched, - ErrorsFound); - } - Pollution.OtherFuel1Coef.Water = state.dataIPShortCut->rNumericArgs(15); - if (!state.dataIPShortCut->lAlphaFieldBlanks(16)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel1", - state.dataIPShortCut->cAlphaFieldNames(16), - state.dataIPShortCut->cAlphaArgs(16), - Pollution.OtherFuel1Coef.WaterSched, - ErrorsFound); - } - Pollution.OtherFuel1Coef.NucHi = state.dataIPShortCut->rNumericArgs(16); - if (!state.dataIPShortCut->lAlphaFieldBlanks(17)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel1", - state.dataIPShortCut->cAlphaFieldNames(17), - state.dataIPShortCut->cAlphaArgs(17), - Pollution.OtherFuel1Coef.NucHiSched, - ErrorsFound); - } - Pollution.OtherFuel1Coef.NucLo = state.dataIPShortCut->rNumericArgs(17); - if (!state.dataIPShortCut->lAlphaFieldBlanks(18)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel1", - state.dataIPShortCut->cAlphaFieldNames(18), - state.dataIPShortCut->cAlphaArgs(18), - Pollution.OtherFuel1Coef.NucLoSched, - ErrorsFound); - } - - } else if (SELECT_CASE_var == "OTHERFUEL2") { - if (Pollution.OtherFuel2Coef.FuelFactorUsed) { - ShowWarningError( - state, format("{}: {} already entered. Previous entry will be used.", cCurrentModuleObject, FuelType.FuelTypeNames(Loop))); - continue; - } - Pollution.OtherFuel2Coef.FuelFactorUsed = true; - // OtherFuel2 Coeffs - Pollution.OtherFuel2Coef.Source = state.dataIPShortCut->rNumericArgs(1); - if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel2", - state.dataIPShortCut->cAlphaFieldNames(2), - state.dataIPShortCut->cAlphaArgs(2), - Pollution.OtherFuel2Coef.SourceSched, - ErrorsFound); - } - Pollution.OtherFuel2Coef.CO2 = state.dataIPShortCut->rNumericArgs(2); - if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel2", - state.dataIPShortCut->cAlphaFieldNames(3), - state.dataIPShortCut->cAlphaArgs(3), - Pollution.OtherFuel2Coef.CO2Sched, - ErrorsFound); - } - Pollution.OtherFuel2Coef.CO = state.dataIPShortCut->rNumericArgs(3); - if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel2", - state.dataIPShortCut->cAlphaFieldNames(4), - state.dataIPShortCut->cAlphaArgs(4), - Pollution.OtherFuel2Coef.COSched, - ErrorsFound); - } - Pollution.OtherFuel2Coef.CH4 = state.dataIPShortCut->rNumericArgs(4); - if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel2", - state.dataIPShortCut->cAlphaFieldNames(5), - state.dataIPShortCut->cAlphaArgs(5), - Pollution.OtherFuel2Coef.CH4Sched, - ErrorsFound); - } - Pollution.OtherFuel2Coef.NOx = state.dataIPShortCut->rNumericArgs(5); - if (!state.dataIPShortCut->lAlphaFieldBlanks(6)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel2", - state.dataIPShortCut->cAlphaFieldNames(6), - state.dataIPShortCut->cAlphaArgs(6), - Pollution.OtherFuel2Coef.NOxSched, - ErrorsFound); - } - Pollution.OtherFuel2Coef.N2O = state.dataIPShortCut->rNumericArgs(6); - if (!state.dataIPShortCut->lAlphaFieldBlanks(7)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel2", - state.dataIPShortCut->cAlphaFieldNames(7), - state.dataIPShortCut->cAlphaArgs(7), - Pollution.OtherFuel2Coef.N2OSched, - ErrorsFound); - } - Pollution.OtherFuel2Coef.SO2 = state.dataIPShortCut->rNumericArgs(7); - if (!state.dataIPShortCut->lAlphaFieldBlanks(8)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel2", - state.dataIPShortCut->cAlphaFieldNames(8), - state.dataIPShortCut->cAlphaArgs(8), - Pollution.OtherFuel2Coef.SO2Sched, - ErrorsFound); - } - Pollution.OtherFuel2Coef.PM = state.dataIPShortCut->rNumericArgs(8); - if (!state.dataIPShortCut->lAlphaFieldBlanks(9)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel2", - state.dataIPShortCut->cAlphaFieldNames(9), - state.dataIPShortCut->cAlphaArgs(9), - Pollution.OtherFuel2Coef.PMSched, - ErrorsFound); - } - Pollution.OtherFuel2Coef.PM10 = state.dataIPShortCut->rNumericArgs(9); - if (!state.dataIPShortCut->lAlphaFieldBlanks(10)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel2", - state.dataIPShortCut->cAlphaFieldNames(10), - state.dataIPShortCut->cAlphaArgs(10), - Pollution.OtherFuel2Coef.PM10Sched, - ErrorsFound); - } - Pollution.OtherFuel2Coef.PM25 = state.dataIPShortCut->rNumericArgs(10); - if (!state.dataIPShortCut->lAlphaFieldBlanks(11)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel2", - state.dataIPShortCut->cAlphaFieldNames(11), - state.dataIPShortCut->cAlphaArgs(11), - Pollution.OtherFuel2Coef.PM25Sched, - ErrorsFound); - } - Pollution.OtherFuel2Coef.NH3 = state.dataIPShortCut->rNumericArgs(11); - if (!state.dataIPShortCut->lAlphaFieldBlanks(12)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel2", - state.dataIPShortCut->cAlphaFieldNames(12), - state.dataIPShortCut->cAlphaArgs(12), - Pollution.OtherFuel2Coef.NH3Sched, - ErrorsFound); - } - Pollution.OtherFuel2Coef.NMVOC = state.dataIPShortCut->rNumericArgs(12); - if (!state.dataIPShortCut->lAlphaFieldBlanks(13)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel2", - state.dataIPShortCut->cAlphaFieldNames(13), - state.dataIPShortCut->cAlphaArgs(13), - Pollution.OtherFuel2Coef.NMVOCSched, - ErrorsFound); - } - Pollution.OtherFuel2Coef.Hg = state.dataIPShortCut->rNumericArgs(13); - if (!state.dataIPShortCut->lAlphaFieldBlanks(14)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel2", - state.dataIPShortCut->cAlphaFieldNames(14), - state.dataIPShortCut->cAlphaArgs(14), - Pollution.OtherFuel2Coef.HgSched, - ErrorsFound); - } - Pollution.OtherFuel2Coef.Pb = state.dataIPShortCut->rNumericArgs(14); - if (!state.dataIPShortCut->lAlphaFieldBlanks(15)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel2", - state.dataIPShortCut->cAlphaFieldNames(15), - state.dataIPShortCut->cAlphaArgs(15), - Pollution.OtherFuel2Coef.PbSched, - ErrorsFound); - } - Pollution.OtherFuel2Coef.Water = state.dataIPShortCut->rNumericArgs(15); - if (!state.dataIPShortCut->lAlphaFieldBlanks(16)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel2", - state.dataIPShortCut->cAlphaFieldNames(16), - state.dataIPShortCut->cAlphaArgs(16), - Pollution.OtherFuel2Coef.WaterSched, - ErrorsFound); - } - Pollution.OtherFuel2Coef.NucHi = state.dataIPShortCut->rNumericArgs(16); - if (!state.dataIPShortCut->lAlphaFieldBlanks(17)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel2", - state.dataIPShortCut->cAlphaFieldNames(17), - state.dataIPShortCut->cAlphaArgs(17), - Pollution.OtherFuel2Coef.NucHiSched, - ErrorsFound); - } - Pollution.OtherFuel2Coef.NucLo = state.dataIPShortCut->rNumericArgs(17); - if (!state.dataIPShortCut->lAlphaFieldBlanks(18)) { - CheckFFSchedule(state, - cCurrentModuleObject, - "OtherFuel2", - state.dataIPShortCut->cAlphaFieldNames(18), - state.dataIPShortCut->cAlphaArgs(18), - Pollution.OtherFuel2Coef.NucLoSched, - ErrorsFound); - } - - } else { - ShowSevereError(state, format("Illegal FuelType for Pollution Calc Entered={}", FuelType.FuelTypeNames(Loop))); - ErrorsFound = true; + switch (FuelType.FuelTypeNames(Loop)) { + case Constant::eFuel::NaturalGas: { + if (Pollution.NatGasCoef.FuelFactorUsed) { + ShowWarningError(state, + format("{}: {} already entered. Previous entry will be used.", + cCurrentModuleObject, + Constant::eFuelNames[static_cast(FuelType.FuelTypeNames(Loop))])); + continue; + } + Pollution.NatGasCoef.FuelFactorUsed = true; + // Natural Gas Coeffs + Pollution.NatGasCoef.Source = state.dataIPShortCut->rNumericArgs(1); + if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "NaturalGas", + state.dataIPShortCut->cAlphaFieldNames(2), + state.dataIPShortCut->cAlphaArgs(2), + Pollution.NatGasCoef.SourceSched, + ErrorsFound); + } + Pollution.NatGasCoef.CO2 = state.dataIPShortCut->rNumericArgs(2); + if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "NaturalGas", + state.dataIPShortCut->cAlphaFieldNames(3), + state.dataIPShortCut->cAlphaArgs(3), + Pollution.NatGasCoef.CO2Sched, + ErrorsFound); + } + Pollution.NatGasCoef.CO = state.dataIPShortCut->rNumericArgs(3); + if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "NaturalGas", + state.dataIPShortCut->cAlphaFieldNames(4), + state.dataIPShortCut->cAlphaArgs(4), + Pollution.NatGasCoef.COSched, + ErrorsFound); + } + Pollution.NatGasCoef.CH4 = state.dataIPShortCut->rNumericArgs(4); + if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "NaturalGas", + state.dataIPShortCut->cAlphaFieldNames(5), + state.dataIPShortCut->cAlphaArgs(5), + Pollution.NatGasCoef.CH4Sched, + ErrorsFound); + } + Pollution.NatGasCoef.NOx = state.dataIPShortCut->rNumericArgs(5); + if (!state.dataIPShortCut->lAlphaFieldBlanks(6)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "NaturalGas", + state.dataIPShortCut->cAlphaFieldNames(6), + state.dataIPShortCut->cAlphaArgs(6), + Pollution.NatGasCoef.NOxSched, + ErrorsFound); + } + Pollution.NatGasCoef.N2O = state.dataIPShortCut->rNumericArgs(6); + if (!state.dataIPShortCut->lAlphaFieldBlanks(7)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "NaturalGas", + state.dataIPShortCut->cAlphaFieldNames(7), + state.dataIPShortCut->cAlphaArgs(7), + Pollution.NatGasCoef.N2OSched, + ErrorsFound); + } + Pollution.NatGasCoef.SO2 = state.dataIPShortCut->rNumericArgs(7); + if (!state.dataIPShortCut->lAlphaFieldBlanks(8)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "NaturalGas", + state.dataIPShortCut->cAlphaFieldNames(8), + state.dataIPShortCut->cAlphaArgs(8), + Pollution.NatGasCoef.SO2Sched, + ErrorsFound); + } + Pollution.NatGasCoef.PM = state.dataIPShortCut->rNumericArgs(8); + if (!state.dataIPShortCut->lAlphaFieldBlanks(9)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "NaturalGas", + state.dataIPShortCut->cAlphaFieldNames(9), + state.dataIPShortCut->cAlphaArgs(9), + Pollution.NatGasCoef.PMSched, + ErrorsFound); + } + Pollution.NatGasCoef.PM10 = state.dataIPShortCut->rNumericArgs(9); + if (!state.dataIPShortCut->lAlphaFieldBlanks(10)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "NaturalGas", + state.dataIPShortCut->cAlphaFieldNames(10), + state.dataIPShortCut->cAlphaArgs(10), + Pollution.NatGasCoef.PM10Sched, + ErrorsFound); + } + Pollution.NatGasCoef.PM25 = state.dataIPShortCut->rNumericArgs(10); + if (!state.dataIPShortCut->lAlphaFieldBlanks(11)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "NaturalGas", + state.dataIPShortCut->cAlphaFieldNames(11), + state.dataIPShortCut->cAlphaArgs(11), + Pollution.NatGasCoef.PM25Sched, + ErrorsFound); + } + Pollution.NatGasCoef.NH3 = state.dataIPShortCut->rNumericArgs(11); + if (!state.dataIPShortCut->lAlphaFieldBlanks(12)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "NaturalGas", + state.dataIPShortCut->cAlphaFieldNames(12), + state.dataIPShortCut->cAlphaArgs(12), + Pollution.NatGasCoef.NH3Sched, + ErrorsFound); + } + Pollution.NatGasCoef.NMVOC = state.dataIPShortCut->rNumericArgs(12); + if (!state.dataIPShortCut->lAlphaFieldBlanks(13)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "NaturalGas", + state.dataIPShortCut->cAlphaFieldNames(13), + state.dataIPShortCut->cAlphaArgs(13), + Pollution.NatGasCoef.NMVOCSched, + ErrorsFound); + } + Pollution.NatGasCoef.Hg = state.dataIPShortCut->rNumericArgs(13); + if (!state.dataIPShortCut->lAlphaFieldBlanks(14)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "NaturalGas", + state.dataIPShortCut->cAlphaFieldNames(14), + state.dataIPShortCut->cAlphaArgs(14), + Pollution.NatGasCoef.HgSched, + ErrorsFound); + } + Pollution.NatGasCoef.Pb = state.dataIPShortCut->rNumericArgs(14); + if (!state.dataIPShortCut->lAlphaFieldBlanks(15)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "NaturalGas", + state.dataIPShortCut->cAlphaFieldNames(15), + state.dataIPShortCut->cAlphaArgs(15), + Pollution.NatGasCoef.PbSched, + ErrorsFound); + } + Pollution.NatGasCoef.Water = state.dataIPShortCut->rNumericArgs(15); + if (!state.dataIPShortCut->lAlphaFieldBlanks(16)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "NaturalGas", + state.dataIPShortCut->cAlphaFieldNames(16), + state.dataIPShortCut->cAlphaArgs(16), + Pollution.NatGasCoef.WaterSched, + ErrorsFound); + } + Pollution.NatGasCoef.NucHi = state.dataIPShortCut->rNumericArgs(16); + if (!state.dataIPShortCut->lAlphaFieldBlanks(17)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "NaturalGas", + state.dataIPShortCut->cAlphaFieldNames(17), + state.dataIPShortCut->cAlphaArgs(17), + Pollution.NatGasCoef.NucHiSched, + ErrorsFound); + } + Pollution.NatGasCoef.NucLo = state.dataIPShortCut->rNumericArgs(17); + if (!state.dataIPShortCut->lAlphaFieldBlanks(18)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "NaturalGas", + state.dataIPShortCut->cAlphaFieldNames(18), + state.dataIPShortCut->cAlphaArgs(18), + Pollution.NatGasCoef.NucLoSched, + ErrorsFound); + } + } break; + case Constant::eFuel::FuelOilNo2: { + if (Pollution.FuelOil2Coef.FuelFactorUsed) { + ShowWarningError(state, + format("{}: {} already entered. Previous entry will be used.", + cCurrentModuleObject, + Constant::eFuelNames[static_cast(FuelType.FuelTypeNames(Loop))])); + continue; + } + Pollution.FuelOil2Coef.FuelFactorUsed = true; + // FuelOilNo2 Coeffs + Pollution.FuelOil2Coef.Source = state.dataIPShortCut->rNumericArgs(1); + if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#2", + state.dataIPShortCut->cAlphaFieldNames(2), + state.dataIPShortCut->cAlphaArgs(2), + Pollution.FuelOil2Coef.SourceSched, + ErrorsFound); + } + Pollution.FuelOil2Coef.CO2 = state.dataIPShortCut->rNumericArgs(2); + if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#2", + state.dataIPShortCut->cAlphaFieldNames(3), + state.dataIPShortCut->cAlphaArgs(3), + Pollution.FuelOil2Coef.CO2Sched, + ErrorsFound); + } + Pollution.FuelOil2Coef.CO = state.dataIPShortCut->rNumericArgs(3); + if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#2", + state.dataIPShortCut->cAlphaFieldNames(4), + state.dataIPShortCut->cAlphaArgs(4), + Pollution.FuelOil2Coef.COSched, + ErrorsFound); + } + Pollution.FuelOil2Coef.CH4 = state.dataIPShortCut->rNumericArgs(4); + if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#2", + state.dataIPShortCut->cAlphaFieldNames(5), + state.dataIPShortCut->cAlphaArgs(5), + Pollution.FuelOil2Coef.CH4Sched, + ErrorsFound); + } + Pollution.FuelOil2Coef.NOx = state.dataIPShortCut->rNumericArgs(5); + if (!state.dataIPShortCut->lAlphaFieldBlanks(6)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#2", + state.dataIPShortCut->cAlphaFieldNames(6), + state.dataIPShortCut->cAlphaArgs(6), + Pollution.FuelOil2Coef.NOxSched, + ErrorsFound); + } + Pollution.FuelOil2Coef.N2O = state.dataIPShortCut->rNumericArgs(6); + if (!state.dataIPShortCut->lAlphaFieldBlanks(7)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#2", + state.dataIPShortCut->cAlphaFieldNames(7), + state.dataIPShortCut->cAlphaArgs(7), + Pollution.FuelOil2Coef.N2OSched, + ErrorsFound); + } + Pollution.FuelOil2Coef.SO2 = state.dataIPShortCut->rNumericArgs(7); + if (!state.dataIPShortCut->lAlphaFieldBlanks(8)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#2", + state.dataIPShortCut->cAlphaFieldNames(8), + state.dataIPShortCut->cAlphaArgs(8), + Pollution.FuelOil2Coef.SO2Sched, + ErrorsFound); + } + Pollution.FuelOil2Coef.PM = state.dataIPShortCut->rNumericArgs(8); + if (!state.dataIPShortCut->lAlphaFieldBlanks(9)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#2", + state.dataIPShortCut->cAlphaFieldNames(9), + state.dataIPShortCut->cAlphaArgs(9), + Pollution.FuelOil2Coef.PMSched, + ErrorsFound); + } + Pollution.FuelOil2Coef.PM10 = state.dataIPShortCut->rNumericArgs(9); + if (!state.dataIPShortCut->lAlphaFieldBlanks(10)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#2", + state.dataIPShortCut->cAlphaFieldNames(10), + state.dataIPShortCut->cAlphaArgs(10), + Pollution.FuelOil2Coef.PM10Sched, + ErrorsFound); + } + Pollution.FuelOil2Coef.PM25 = state.dataIPShortCut->rNumericArgs(10); + if (!state.dataIPShortCut->lAlphaFieldBlanks(11)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#2", + state.dataIPShortCut->cAlphaFieldNames(11), + state.dataIPShortCut->cAlphaArgs(11), + Pollution.FuelOil2Coef.PM25Sched, + ErrorsFound); + } + Pollution.FuelOil2Coef.NH3 = state.dataIPShortCut->rNumericArgs(11); + if (!state.dataIPShortCut->lAlphaFieldBlanks(12)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#2", + state.dataIPShortCut->cAlphaFieldNames(12), + state.dataIPShortCut->cAlphaArgs(12), + Pollution.FuelOil2Coef.NH3Sched, + ErrorsFound); + } + Pollution.FuelOil2Coef.NMVOC = state.dataIPShortCut->rNumericArgs(12); + if (!state.dataIPShortCut->lAlphaFieldBlanks(13)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#2", + state.dataIPShortCut->cAlphaFieldNames(13), + state.dataIPShortCut->cAlphaArgs(13), + Pollution.FuelOil2Coef.NMVOCSched, + ErrorsFound); + } + Pollution.FuelOil2Coef.Hg = state.dataIPShortCut->rNumericArgs(13); + if (!state.dataIPShortCut->lAlphaFieldBlanks(14)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#2", + state.dataIPShortCut->cAlphaFieldNames(14), + state.dataIPShortCut->cAlphaArgs(14), + Pollution.FuelOil2Coef.HgSched, + ErrorsFound); + } + Pollution.FuelOil2Coef.Pb = state.dataIPShortCut->rNumericArgs(14); + if (!state.dataIPShortCut->lAlphaFieldBlanks(15)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#2", + state.dataIPShortCut->cAlphaFieldNames(15), + state.dataIPShortCut->cAlphaArgs(15), + Pollution.FuelOil2Coef.PbSched, + ErrorsFound); + } + Pollution.FuelOil2Coef.Water = state.dataIPShortCut->rNumericArgs(15); + if (!state.dataIPShortCut->lAlphaFieldBlanks(16)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#2", + state.dataIPShortCut->cAlphaFieldNames(16), + state.dataIPShortCut->cAlphaArgs(16), + Pollution.FuelOil2Coef.WaterSched, + ErrorsFound); + } + Pollution.FuelOil2Coef.NucHi = state.dataIPShortCut->rNumericArgs(16); + if (!state.dataIPShortCut->lAlphaFieldBlanks(17)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#2", + state.dataIPShortCut->cAlphaFieldNames(17), + state.dataIPShortCut->cAlphaArgs(17), + Pollution.FuelOil2Coef.NucHiSched, + ErrorsFound); + } + Pollution.FuelOil2Coef.NucLo = state.dataIPShortCut->rNumericArgs(17); + if (!state.dataIPShortCut->lAlphaFieldBlanks(18)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#2", + state.dataIPShortCut->cAlphaFieldNames(18), + state.dataIPShortCut->cAlphaArgs(18), + Pollution.FuelOil2Coef.NucLoSched, + ErrorsFound); + } + } break; + case Constant::eFuel::FuelOilNo1: { + if (Pollution.FuelOil1Coef.FuelFactorUsed) { + ShowWarningError(state, + format("{}: {} already entered. Previous entry will be used.", + cCurrentModuleObject, + Constant::eFuelNames[static_cast(FuelType.FuelTypeNames(Loop))])); + continue; + } + Pollution.FuelOil1Coef.FuelFactorUsed = true; + // FuelOilNo1 Coeffs + Pollution.FuelOil1Coef.Source = state.dataIPShortCut->rNumericArgs(1); + if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#1", + state.dataIPShortCut->cAlphaFieldNames(2), + state.dataIPShortCut->cAlphaArgs(2), + Pollution.FuelOil1Coef.SourceSched, + ErrorsFound); + } + Pollution.FuelOil1Coef.CO2 = state.dataIPShortCut->rNumericArgs(2); + if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#1", + state.dataIPShortCut->cAlphaFieldNames(3), + state.dataIPShortCut->cAlphaArgs(3), + Pollution.FuelOil1Coef.CO2Sched, + ErrorsFound); + } + Pollution.FuelOil1Coef.CO = state.dataIPShortCut->rNumericArgs(3); + if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#1", + state.dataIPShortCut->cAlphaFieldNames(4), + state.dataIPShortCut->cAlphaArgs(4), + Pollution.FuelOil1Coef.COSched, + ErrorsFound); + } + Pollution.FuelOil1Coef.CH4 = state.dataIPShortCut->rNumericArgs(4); + if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#1", + state.dataIPShortCut->cAlphaFieldNames(5), + state.dataIPShortCut->cAlphaArgs(5), + Pollution.FuelOil1Coef.CH4Sched, + ErrorsFound); + } + Pollution.FuelOil1Coef.NOx = state.dataIPShortCut->rNumericArgs(5); + if (!state.dataIPShortCut->lAlphaFieldBlanks(6)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#1", + state.dataIPShortCut->cAlphaFieldNames(6), + state.dataIPShortCut->cAlphaArgs(6), + Pollution.FuelOil1Coef.NOxSched, + ErrorsFound); + } + Pollution.FuelOil1Coef.N2O = state.dataIPShortCut->rNumericArgs(6); + if (!state.dataIPShortCut->lAlphaFieldBlanks(7)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#1", + state.dataIPShortCut->cAlphaFieldNames(7), + state.dataIPShortCut->cAlphaArgs(7), + Pollution.FuelOil1Coef.N2OSched, + ErrorsFound); + } + Pollution.FuelOil1Coef.SO2 = state.dataIPShortCut->rNumericArgs(7); + if (!state.dataIPShortCut->lAlphaFieldBlanks(8)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#1", + state.dataIPShortCut->cAlphaFieldNames(8), + state.dataIPShortCut->cAlphaArgs(8), + Pollution.FuelOil1Coef.SO2Sched, + ErrorsFound); + } + Pollution.FuelOil1Coef.PM = state.dataIPShortCut->rNumericArgs(8); + if (!state.dataIPShortCut->lAlphaFieldBlanks(9)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#1", + state.dataIPShortCut->cAlphaFieldNames(9), + state.dataIPShortCut->cAlphaArgs(9), + Pollution.FuelOil1Coef.PMSched, + ErrorsFound); + } + Pollution.FuelOil1Coef.PM10 = state.dataIPShortCut->rNumericArgs(9); + if (!state.dataIPShortCut->lAlphaFieldBlanks(10)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#1", + state.dataIPShortCut->cAlphaFieldNames(10), + state.dataIPShortCut->cAlphaArgs(10), + Pollution.FuelOil1Coef.PM10Sched, + ErrorsFound); + } + Pollution.FuelOil1Coef.PM25 = state.dataIPShortCut->rNumericArgs(10); + if (!state.dataIPShortCut->lAlphaFieldBlanks(11)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#1", + state.dataIPShortCut->cAlphaFieldNames(11), + state.dataIPShortCut->cAlphaArgs(11), + Pollution.FuelOil1Coef.PM25Sched, + ErrorsFound); + } + Pollution.FuelOil1Coef.NH3 = state.dataIPShortCut->rNumericArgs(11); + if (!state.dataIPShortCut->lAlphaFieldBlanks(12)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#1", + state.dataIPShortCut->cAlphaFieldNames(12), + state.dataIPShortCut->cAlphaArgs(12), + Pollution.FuelOil1Coef.NH3Sched, + ErrorsFound); + } + Pollution.FuelOil1Coef.NMVOC = state.dataIPShortCut->rNumericArgs(12); + if (!state.dataIPShortCut->lAlphaFieldBlanks(13)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#1", + state.dataIPShortCut->cAlphaFieldNames(13), + state.dataIPShortCut->cAlphaArgs(13), + Pollution.FuelOil1Coef.NMVOCSched, + ErrorsFound); + } + Pollution.FuelOil1Coef.Hg = state.dataIPShortCut->rNumericArgs(13); + if (!state.dataIPShortCut->lAlphaFieldBlanks(14)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#1", + state.dataIPShortCut->cAlphaFieldNames(14), + state.dataIPShortCut->cAlphaArgs(14), + Pollution.FuelOil1Coef.HgSched, + ErrorsFound); + } + Pollution.FuelOil1Coef.Pb = state.dataIPShortCut->rNumericArgs(14); + if (!state.dataIPShortCut->lAlphaFieldBlanks(15)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#1", + state.dataIPShortCut->cAlphaFieldNames(15), + state.dataIPShortCut->cAlphaArgs(15), + Pollution.FuelOil1Coef.PbSched, + ErrorsFound); + } + Pollution.FuelOil1Coef.Water = state.dataIPShortCut->rNumericArgs(15); + if (!state.dataIPShortCut->lAlphaFieldBlanks(16)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#1", + state.dataIPShortCut->cAlphaFieldNames(16), + state.dataIPShortCut->cAlphaArgs(16), + Pollution.FuelOil1Coef.WaterSched, + ErrorsFound); + } + Pollution.FuelOil1Coef.NucHi = state.dataIPShortCut->rNumericArgs(16); + if (!state.dataIPShortCut->lAlphaFieldBlanks(17)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#1", + state.dataIPShortCut->cAlphaFieldNames(17), + state.dataIPShortCut->cAlphaArgs(17), + Pollution.FuelOil1Coef.NucHiSched, + ErrorsFound); + } + Pollution.FuelOil1Coef.NucLo = state.dataIPShortCut->rNumericArgs(17); + if (!state.dataIPShortCut->lAlphaFieldBlanks(18)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Fuel Oil#1", + state.dataIPShortCut->cAlphaFieldNames(18), + state.dataIPShortCut->cAlphaArgs(18), + Pollution.FuelOil1Coef.NucLoSched, + ErrorsFound); + } + } break; + case Constant::eFuel::Coal: { + if (Pollution.CoalCoef.FuelFactorUsed) { + ShowWarningError(state, + format("{}: {} already entered. Previous entry will be used.", + cCurrentModuleObject, + Constant::eFuelNames[static_cast(FuelType.FuelTypeNames(Loop))])); + continue; + } + Pollution.CoalCoef.FuelFactorUsed = true; + // Coal + Pollution.CoalCoef.Source = state.dataIPShortCut->rNumericArgs(1); + if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Coal", + state.dataIPShortCut->cAlphaFieldNames(2), + state.dataIPShortCut->cAlphaArgs(2), + Pollution.CoalCoef.SourceSched, + ErrorsFound); + } + Pollution.CoalCoef.CO2 = state.dataIPShortCut->rNumericArgs(2); + if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Coal", + state.dataIPShortCut->cAlphaFieldNames(3), + state.dataIPShortCut->cAlphaArgs(3), + Pollution.CoalCoef.CO2Sched, + ErrorsFound); + } + Pollution.CoalCoef.CO = state.dataIPShortCut->rNumericArgs(3); + if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Coal", + state.dataIPShortCut->cAlphaFieldNames(4), + state.dataIPShortCut->cAlphaArgs(4), + Pollution.CoalCoef.COSched, + ErrorsFound); + } + Pollution.CoalCoef.CH4 = state.dataIPShortCut->rNumericArgs(4); + if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Coal", + state.dataIPShortCut->cAlphaFieldNames(5), + state.dataIPShortCut->cAlphaArgs(5), + Pollution.CoalCoef.CH4Sched, + ErrorsFound); + } + Pollution.CoalCoef.NOx = state.dataIPShortCut->rNumericArgs(5); + if (!state.dataIPShortCut->lAlphaFieldBlanks(6)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Coal", + state.dataIPShortCut->cAlphaFieldNames(6), + state.dataIPShortCut->cAlphaArgs(6), + Pollution.CoalCoef.NOxSched, + ErrorsFound); + } + Pollution.CoalCoef.N2O = state.dataIPShortCut->rNumericArgs(6); + if (!state.dataIPShortCut->lAlphaFieldBlanks(7)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Coal", + state.dataIPShortCut->cAlphaFieldNames(7), + state.dataIPShortCut->cAlphaArgs(7), + Pollution.CoalCoef.N2OSched, + ErrorsFound); + } + Pollution.CoalCoef.SO2 = state.dataIPShortCut->rNumericArgs(7); + if (!state.dataIPShortCut->lAlphaFieldBlanks(8)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Coal", + state.dataIPShortCut->cAlphaFieldNames(8), + state.dataIPShortCut->cAlphaArgs(8), + Pollution.CoalCoef.SO2Sched, + ErrorsFound); + } + Pollution.CoalCoef.PM = state.dataIPShortCut->rNumericArgs(8); + if (!state.dataIPShortCut->lAlphaFieldBlanks(9)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Coal", + state.dataIPShortCut->cAlphaFieldNames(9), + state.dataIPShortCut->cAlphaArgs(9), + Pollution.CoalCoef.PMSched, + ErrorsFound); + } + Pollution.CoalCoef.PM10 = state.dataIPShortCut->rNumericArgs(9); + if (!state.dataIPShortCut->lAlphaFieldBlanks(10)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Coal", + state.dataIPShortCut->cAlphaFieldNames(10), + state.dataIPShortCut->cAlphaArgs(10), + Pollution.CoalCoef.PM10Sched, + ErrorsFound); + } + Pollution.CoalCoef.PM25 = state.dataIPShortCut->rNumericArgs(10); + if (!state.dataIPShortCut->lAlphaFieldBlanks(11)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Coal", + state.dataIPShortCut->cAlphaFieldNames(11), + state.dataIPShortCut->cAlphaArgs(11), + Pollution.CoalCoef.PM25Sched, + ErrorsFound); + } + Pollution.CoalCoef.NH3 = state.dataIPShortCut->rNumericArgs(11); + if (!state.dataIPShortCut->lAlphaFieldBlanks(12)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Coal", + state.dataIPShortCut->cAlphaFieldNames(12), + state.dataIPShortCut->cAlphaArgs(12), + Pollution.CoalCoef.NH3Sched, + ErrorsFound); + } + Pollution.CoalCoef.NMVOC = state.dataIPShortCut->rNumericArgs(12); + if (!state.dataIPShortCut->lAlphaFieldBlanks(13)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Coal", + state.dataIPShortCut->cAlphaFieldNames(13), + state.dataIPShortCut->cAlphaArgs(13), + Pollution.CoalCoef.NMVOCSched, + ErrorsFound); + } + Pollution.CoalCoef.Hg = state.dataIPShortCut->rNumericArgs(13); + if (!state.dataIPShortCut->lAlphaFieldBlanks(14)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Coal", + state.dataIPShortCut->cAlphaFieldNames(14), + state.dataIPShortCut->cAlphaArgs(14), + Pollution.CoalCoef.HgSched, + ErrorsFound); + } + Pollution.CoalCoef.Pb = state.dataIPShortCut->rNumericArgs(14); + if (!state.dataIPShortCut->lAlphaFieldBlanks(15)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Coal", + state.dataIPShortCut->cAlphaFieldNames(15), + state.dataIPShortCut->cAlphaArgs(15), + Pollution.CoalCoef.PbSched, + ErrorsFound); + } + Pollution.CoalCoef.Water = state.dataIPShortCut->rNumericArgs(15); + if (!state.dataIPShortCut->lAlphaFieldBlanks(16)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Coal", + state.dataIPShortCut->cAlphaFieldNames(16), + state.dataIPShortCut->cAlphaArgs(16), + Pollution.CoalCoef.WaterSched, + ErrorsFound); + } + Pollution.CoalCoef.NucHi = state.dataIPShortCut->rNumericArgs(16); + if (!state.dataIPShortCut->lAlphaFieldBlanks(17)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Coal", + state.dataIPShortCut->cAlphaFieldNames(17), + state.dataIPShortCut->cAlphaArgs(17), + Pollution.CoalCoef.NucHiSched, + ErrorsFound); + } + Pollution.CoalCoef.NucLo = state.dataIPShortCut->rNumericArgs(17); + if (!state.dataIPShortCut->lAlphaFieldBlanks(18)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Coal", + state.dataIPShortCut->cAlphaFieldNames(18), + state.dataIPShortCut->cAlphaArgs(18), + Pollution.CoalCoef.NucLoSched, + ErrorsFound); + } + } break; + case Constant::eFuel::Electricity: { + if (Pollution.ElecCoef.FuelFactorUsed) { + ShowWarningError(state, + format("{}: {} already entered. Previous entry will be used.", + cCurrentModuleObject, + Constant::eFuelNames[static_cast(FuelType.FuelTypeNames(Loop))])); + continue; + } + Pollution.ElecCoef.FuelFactorUsed = true; + // Electric Coeffs + Pollution.ElecCoef.Source = state.dataIPShortCut->rNumericArgs(1); + if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Electricity", + state.dataIPShortCut->cAlphaFieldNames(2), + state.dataIPShortCut->cAlphaArgs(2), + Pollution.ElecCoef.SourceSched, + ErrorsFound); + } + Pollution.ElecCoef.CO2 = state.dataIPShortCut->rNumericArgs(2); + if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Electricity", + state.dataIPShortCut->cAlphaFieldNames(3), + state.dataIPShortCut->cAlphaArgs(3), + Pollution.ElecCoef.CO2Sched, + ErrorsFound); + } + Pollution.ElecCoef.CO = state.dataIPShortCut->rNumericArgs(3); + if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Electricity", + state.dataIPShortCut->cAlphaFieldNames(4), + state.dataIPShortCut->cAlphaArgs(4), + Pollution.ElecCoef.COSched, + ErrorsFound); + } + Pollution.ElecCoef.CH4 = state.dataIPShortCut->rNumericArgs(4); + if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Electricity", + state.dataIPShortCut->cAlphaFieldNames(5), + state.dataIPShortCut->cAlphaArgs(5), + Pollution.ElecCoef.CH4Sched, + ErrorsFound); + } + Pollution.ElecCoef.NOx = state.dataIPShortCut->rNumericArgs(5); + if (!state.dataIPShortCut->lAlphaFieldBlanks(6)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Electricity", + state.dataIPShortCut->cAlphaFieldNames(6), + state.dataIPShortCut->cAlphaArgs(6), + Pollution.ElecCoef.NOxSched, + ErrorsFound); + } + Pollution.ElecCoef.N2O = state.dataIPShortCut->rNumericArgs(6); + if (!state.dataIPShortCut->lAlphaFieldBlanks(7)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Electricity", + state.dataIPShortCut->cAlphaFieldNames(7), + state.dataIPShortCut->cAlphaArgs(7), + Pollution.ElecCoef.N2OSched, + ErrorsFound); + } + Pollution.ElecCoef.SO2 = state.dataIPShortCut->rNumericArgs(7); + if (!state.dataIPShortCut->lAlphaFieldBlanks(8)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Electricity", + state.dataIPShortCut->cAlphaFieldNames(8), + state.dataIPShortCut->cAlphaArgs(8), + Pollution.ElecCoef.SO2Sched, + ErrorsFound); + } + Pollution.ElecCoef.PM = state.dataIPShortCut->rNumericArgs(8); + if (!state.dataIPShortCut->lAlphaFieldBlanks(9)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Electricity", + state.dataIPShortCut->cAlphaFieldNames(9), + state.dataIPShortCut->cAlphaArgs(9), + Pollution.ElecCoef.PMSched, + ErrorsFound); + } + Pollution.ElecCoef.PM10 = state.dataIPShortCut->rNumericArgs(9); + if (!state.dataIPShortCut->lAlphaFieldBlanks(10)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Electricity", + state.dataIPShortCut->cAlphaFieldNames(10), + state.dataIPShortCut->cAlphaArgs(10), + Pollution.ElecCoef.PM10Sched, + ErrorsFound); + } + Pollution.ElecCoef.PM25 = state.dataIPShortCut->rNumericArgs(10); + if (!state.dataIPShortCut->lAlphaFieldBlanks(11)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Electricity", + state.dataIPShortCut->cAlphaFieldNames(11), + state.dataIPShortCut->cAlphaArgs(11), + Pollution.ElecCoef.PM25Sched, + ErrorsFound); + } + Pollution.ElecCoef.NH3 = state.dataIPShortCut->rNumericArgs(11); + if (!state.dataIPShortCut->lAlphaFieldBlanks(12)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Electricity", + state.dataIPShortCut->cAlphaFieldNames(12), + state.dataIPShortCut->cAlphaArgs(12), + Pollution.ElecCoef.NH3Sched, + ErrorsFound); + } + Pollution.ElecCoef.NMVOC = state.dataIPShortCut->rNumericArgs(12); + if (!state.dataIPShortCut->lAlphaFieldBlanks(13)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Electricity", + state.dataIPShortCut->cAlphaFieldNames(13), + state.dataIPShortCut->cAlphaArgs(13), + Pollution.ElecCoef.NMVOCSched, + ErrorsFound); + } + Pollution.ElecCoef.Hg = state.dataIPShortCut->rNumericArgs(13); + if (!state.dataIPShortCut->lAlphaFieldBlanks(14)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Electricity", + state.dataIPShortCut->cAlphaFieldNames(14), + state.dataIPShortCut->cAlphaArgs(14), + Pollution.ElecCoef.HgSched, + ErrorsFound); + } + Pollution.ElecCoef.Pb = state.dataIPShortCut->rNumericArgs(14); + if (!state.dataIPShortCut->lAlphaFieldBlanks(15)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Electricity", + state.dataIPShortCut->cAlphaFieldNames(15), + state.dataIPShortCut->cAlphaArgs(15), + Pollution.ElecCoef.PbSched, + ErrorsFound); + } + Pollution.ElecCoef.Water = state.dataIPShortCut->rNumericArgs(15); + if (!state.dataIPShortCut->lAlphaFieldBlanks(16)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Electricity", + state.dataIPShortCut->cAlphaFieldNames(16), + state.dataIPShortCut->cAlphaArgs(16), + Pollution.ElecCoef.WaterSched, + ErrorsFound); } + Pollution.ElecCoef.NucHi = state.dataIPShortCut->rNumericArgs(16); + if (!state.dataIPShortCut->lAlphaFieldBlanks(17)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Electricity", + state.dataIPShortCut->cAlphaFieldNames(17), + state.dataIPShortCut->cAlphaArgs(17), + Pollution.ElecCoef.NucHiSched, + ErrorsFound); + } + Pollution.ElecCoef.NucLo = state.dataIPShortCut->rNumericArgs(17); + if (!state.dataIPShortCut->lAlphaFieldBlanks(18)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Electricity", + state.dataIPShortCut->cAlphaFieldNames(18), + state.dataIPShortCut->cAlphaArgs(18), + Pollution.ElecCoef.NucLoSched, + ErrorsFound); + } + } break; + case Constant::eFuel::Gasoline: { + if (Pollution.GasolineCoef.FuelFactorUsed) { + ShowWarningError(state, + format("{}: {} already entered. Previous entry will be used.", + cCurrentModuleObject, + Constant::eFuelNames[static_cast(FuelType.FuelTypeNames(Loop))])); + continue; + } + Pollution.GasolineCoef.FuelFactorUsed = true; + // Gasoline Coeffs + Pollution.GasolineCoef.Source = state.dataIPShortCut->rNumericArgs(1); + if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Gasoline", + state.dataIPShortCut->cAlphaFieldNames(2), + state.dataIPShortCut->cAlphaArgs(2), + Pollution.GasolineCoef.SourceSched, + ErrorsFound); + } + Pollution.GasolineCoef.CO2 = state.dataIPShortCut->rNumericArgs(2); + if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Gasoline", + state.dataIPShortCut->cAlphaFieldNames(3), + state.dataIPShortCut->cAlphaArgs(3), + Pollution.GasolineCoef.CO2Sched, + ErrorsFound); + } + Pollution.GasolineCoef.CO = state.dataIPShortCut->rNumericArgs(3); + if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Gasoline", + state.dataIPShortCut->cAlphaFieldNames(4), + state.dataIPShortCut->cAlphaArgs(4), + Pollution.GasolineCoef.COSched, + ErrorsFound); + } + Pollution.GasolineCoef.CH4 = state.dataIPShortCut->rNumericArgs(4); + if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Gasoline", + state.dataIPShortCut->cAlphaFieldNames(5), + state.dataIPShortCut->cAlphaArgs(5), + Pollution.GasolineCoef.CH4Sched, + ErrorsFound); + } + Pollution.GasolineCoef.NOx = state.dataIPShortCut->rNumericArgs(5); + if (!state.dataIPShortCut->lAlphaFieldBlanks(6)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Gasoline", + state.dataIPShortCut->cAlphaFieldNames(6), + state.dataIPShortCut->cAlphaArgs(6), + Pollution.GasolineCoef.NOxSched, + ErrorsFound); + } + Pollution.GasolineCoef.N2O = state.dataIPShortCut->rNumericArgs(6); + if (!state.dataIPShortCut->lAlphaFieldBlanks(7)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Gasoline", + state.dataIPShortCut->cAlphaFieldNames(7), + state.dataIPShortCut->cAlphaArgs(7), + Pollution.GasolineCoef.N2OSched, + ErrorsFound); + } + Pollution.GasolineCoef.SO2 = state.dataIPShortCut->rNumericArgs(7); + if (!state.dataIPShortCut->lAlphaFieldBlanks(8)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Gasoline", + state.dataIPShortCut->cAlphaFieldNames(8), + state.dataIPShortCut->cAlphaArgs(8), + Pollution.GasolineCoef.SO2Sched, + ErrorsFound); + } + Pollution.GasolineCoef.PM = state.dataIPShortCut->rNumericArgs(8); + if (!state.dataIPShortCut->lAlphaFieldBlanks(9)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Gasoline", + state.dataIPShortCut->cAlphaFieldNames(9), + state.dataIPShortCut->cAlphaArgs(9), + Pollution.GasolineCoef.PMSched, + ErrorsFound); + } + Pollution.GasolineCoef.PM10 = state.dataIPShortCut->rNumericArgs(9); + if (!state.dataIPShortCut->lAlphaFieldBlanks(10)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Gasoline", + state.dataIPShortCut->cAlphaFieldNames(10), + state.dataIPShortCut->cAlphaArgs(10), + Pollution.GasolineCoef.PM10Sched, + ErrorsFound); + } + Pollution.GasolineCoef.PM25 = state.dataIPShortCut->rNumericArgs(10); + if (!state.dataIPShortCut->lAlphaFieldBlanks(11)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Gasoline", + state.dataIPShortCut->cAlphaFieldNames(11), + state.dataIPShortCut->cAlphaArgs(11), + Pollution.GasolineCoef.PM25Sched, + ErrorsFound); + } + Pollution.GasolineCoef.NH3 = state.dataIPShortCut->rNumericArgs(11); + if (!state.dataIPShortCut->lAlphaFieldBlanks(12)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Gasoline", + state.dataIPShortCut->cAlphaFieldNames(12), + state.dataIPShortCut->cAlphaArgs(12), + Pollution.GasolineCoef.NH3Sched, + ErrorsFound); + } + Pollution.GasolineCoef.NMVOC = state.dataIPShortCut->rNumericArgs(12); + if (!state.dataIPShortCut->lAlphaFieldBlanks(13)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Gasoline", + state.dataIPShortCut->cAlphaFieldNames(13), + state.dataIPShortCut->cAlphaArgs(13), + Pollution.GasolineCoef.NMVOCSched, + ErrorsFound); + } + Pollution.GasolineCoef.Hg = state.dataIPShortCut->rNumericArgs(13); + if (!state.dataIPShortCut->lAlphaFieldBlanks(14)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Gasoline", + state.dataIPShortCut->cAlphaFieldNames(14), + state.dataIPShortCut->cAlphaArgs(14), + Pollution.GasolineCoef.HgSched, + ErrorsFound); + } + Pollution.GasolineCoef.Pb = state.dataIPShortCut->rNumericArgs(14); + if (!state.dataIPShortCut->lAlphaFieldBlanks(15)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Gasoline", + state.dataIPShortCut->cAlphaFieldNames(15), + state.dataIPShortCut->cAlphaArgs(15), + Pollution.GasolineCoef.PbSched, + ErrorsFound); + } + Pollution.GasolineCoef.Water = state.dataIPShortCut->rNumericArgs(15); + if (!state.dataIPShortCut->lAlphaFieldBlanks(16)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Gasoline", + state.dataIPShortCut->cAlphaFieldNames(16), + state.dataIPShortCut->cAlphaArgs(16), + Pollution.GasolineCoef.WaterSched, + ErrorsFound); + } + Pollution.GasolineCoef.NucHi = state.dataIPShortCut->rNumericArgs(16); + if (!state.dataIPShortCut->lAlphaFieldBlanks(17)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Gasoline", + state.dataIPShortCut->cAlphaFieldNames(17), + state.dataIPShortCut->cAlphaArgs(17), + Pollution.GasolineCoef.NucHiSched, + ErrorsFound); + } + Pollution.GasolineCoef.NucLo = state.dataIPShortCut->rNumericArgs(17); + if (!state.dataIPShortCut->lAlphaFieldBlanks(18)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Gasoline", + state.dataIPShortCut->cAlphaFieldNames(18), + state.dataIPShortCut->cAlphaArgs(18), + Pollution.GasolineCoef.NucLoSched, + ErrorsFound); + } + } break; + case Constant::eFuel::Propane: { + if (Pollution.PropaneCoef.FuelFactorUsed) { + ShowWarningError(state, + format("{}: {} already entered. Previous entry will be used.", + cCurrentModuleObject, + Constant::eFuelNames[static_cast(FuelType.FuelTypeNames(Loop))])); + continue; + } + Pollution.PropaneCoef.FuelFactorUsed = true; + // Propane Coeffs + Pollution.PropaneCoef.Source = state.dataIPShortCut->rNumericArgs(1); + if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Propane", + state.dataIPShortCut->cAlphaFieldNames(2), + state.dataIPShortCut->cAlphaArgs(2), + Pollution.PropaneCoef.SourceSched, + ErrorsFound); + } + Pollution.PropaneCoef.CO2 = state.dataIPShortCut->rNumericArgs(2); + if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Propane", + state.dataIPShortCut->cAlphaFieldNames(3), + state.dataIPShortCut->cAlphaArgs(3), + Pollution.PropaneCoef.CO2Sched, + ErrorsFound); + } + Pollution.PropaneCoef.CO = state.dataIPShortCut->rNumericArgs(3); + if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Propane", + state.dataIPShortCut->cAlphaFieldNames(4), + state.dataIPShortCut->cAlphaArgs(4), + Pollution.PropaneCoef.COSched, + ErrorsFound); + } + Pollution.PropaneCoef.CH4 = state.dataIPShortCut->rNumericArgs(4); + if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Propane", + state.dataIPShortCut->cAlphaFieldNames(5), + state.dataIPShortCut->cAlphaArgs(5), + Pollution.PropaneCoef.CH4Sched, + ErrorsFound); + } + Pollution.PropaneCoef.NOx = state.dataIPShortCut->rNumericArgs(5); + if (!state.dataIPShortCut->lAlphaFieldBlanks(6)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Propane", + state.dataIPShortCut->cAlphaFieldNames(6), + state.dataIPShortCut->cAlphaArgs(6), + Pollution.PropaneCoef.NOxSched, + ErrorsFound); + } + Pollution.PropaneCoef.N2O = state.dataIPShortCut->rNumericArgs(6); + if (!state.dataIPShortCut->lAlphaFieldBlanks(7)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Propane", + state.dataIPShortCut->cAlphaFieldNames(7), + state.dataIPShortCut->cAlphaArgs(7), + Pollution.PropaneCoef.N2OSched, + ErrorsFound); + } + Pollution.PropaneCoef.SO2 = state.dataIPShortCut->rNumericArgs(7); + if (!state.dataIPShortCut->lAlphaFieldBlanks(8)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Propane", + state.dataIPShortCut->cAlphaFieldNames(8), + state.dataIPShortCut->cAlphaArgs(8), + Pollution.PropaneCoef.SO2Sched, + ErrorsFound); + } + Pollution.PropaneCoef.PM = state.dataIPShortCut->rNumericArgs(8); + if (!state.dataIPShortCut->lAlphaFieldBlanks(9)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Propane", + state.dataIPShortCut->cAlphaFieldNames(9), + state.dataIPShortCut->cAlphaArgs(9), + Pollution.PropaneCoef.PMSched, + ErrorsFound); + } + Pollution.PropaneCoef.PM10 = state.dataIPShortCut->rNumericArgs(9); + if (!state.dataIPShortCut->lAlphaFieldBlanks(10)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Propane", + state.dataIPShortCut->cAlphaFieldNames(10), + state.dataIPShortCut->cAlphaArgs(10), + Pollution.PropaneCoef.PM10Sched, + ErrorsFound); + } + Pollution.PropaneCoef.PM25 = state.dataIPShortCut->rNumericArgs(10); + if (!state.dataIPShortCut->lAlphaFieldBlanks(11)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Propane", + state.dataIPShortCut->cAlphaFieldNames(11), + state.dataIPShortCut->cAlphaArgs(11), + Pollution.PropaneCoef.PM25Sched, + ErrorsFound); + } + Pollution.PropaneCoef.NH3 = state.dataIPShortCut->rNumericArgs(11); + if (!state.dataIPShortCut->lAlphaFieldBlanks(12)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Propane", + state.dataIPShortCut->cAlphaFieldNames(12), + state.dataIPShortCut->cAlphaArgs(12), + Pollution.PropaneCoef.NH3Sched, + ErrorsFound); + } + Pollution.PropaneCoef.NMVOC = state.dataIPShortCut->rNumericArgs(12); + if (!state.dataIPShortCut->lAlphaFieldBlanks(13)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Propane", + state.dataIPShortCut->cAlphaFieldNames(13), + state.dataIPShortCut->cAlphaArgs(13), + Pollution.PropaneCoef.NMVOCSched, + ErrorsFound); + } + Pollution.PropaneCoef.Hg = state.dataIPShortCut->rNumericArgs(13); + if (!state.dataIPShortCut->lAlphaFieldBlanks(14)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Propane", + state.dataIPShortCut->cAlphaFieldNames(14), + state.dataIPShortCut->cAlphaArgs(14), + Pollution.PropaneCoef.HgSched, + ErrorsFound); + } + Pollution.PropaneCoef.Pb = state.dataIPShortCut->rNumericArgs(14); + if (!state.dataIPShortCut->lAlphaFieldBlanks(15)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Propane", + state.dataIPShortCut->cAlphaFieldNames(15), + state.dataIPShortCut->cAlphaArgs(15), + Pollution.PropaneCoef.PbSched, + ErrorsFound); + } + Pollution.PropaneCoef.Water = state.dataIPShortCut->rNumericArgs(15); + if (!state.dataIPShortCut->lAlphaFieldBlanks(16)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Propane", + state.dataIPShortCut->cAlphaFieldNames(16), + state.dataIPShortCut->cAlphaArgs(16), + Pollution.PropaneCoef.WaterSched, + ErrorsFound); + } + Pollution.PropaneCoef.NucHi = state.dataIPShortCut->rNumericArgs(16); + if (!state.dataIPShortCut->lAlphaFieldBlanks(17)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Propane", + state.dataIPShortCut->cAlphaFieldNames(17), + state.dataIPShortCut->cAlphaArgs(17), + Pollution.PropaneCoef.NucHiSched, + ErrorsFound); + } + Pollution.PropaneCoef.NucLo = state.dataIPShortCut->rNumericArgs(17); + if (!state.dataIPShortCut->lAlphaFieldBlanks(18)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Propane", + state.dataIPShortCut->cAlphaFieldNames(18), + state.dataIPShortCut->cAlphaArgs(18), + Pollution.PropaneCoef.NucLoSched, + ErrorsFound); + } + } break; + case Constant::eFuel::Diesel: { + if (Pollution.DieselCoef.FuelFactorUsed) { + ShowWarningError(state, + format("{}: {} already entered. Previous entry will be used.", + cCurrentModuleObject, + Constant::eFuelNames[static_cast(FuelType.FuelTypeNames(Loop))])); + continue; + } + Pollution.DieselCoef.FuelFactorUsed = true; + // Diesel Coeffs + Pollution.DieselCoef.Source = state.dataIPShortCut->rNumericArgs(1); + if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Diesel", + state.dataIPShortCut->cAlphaFieldNames(2), + state.dataIPShortCut->cAlphaArgs(2), + Pollution.DieselCoef.SourceSched, + ErrorsFound); + } + Pollution.DieselCoef.CO2 = state.dataIPShortCut->rNumericArgs(2); + if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Diesel", + state.dataIPShortCut->cAlphaFieldNames(3), + state.dataIPShortCut->cAlphaArgs(3), + Pollution.DieselCoef.CO2Sched, + ErrorsFound); + } + Pollution.DieselCoef.CO = state.dataIPShortCut->rNumericArgs(3); + if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Diesel", + state.dataIPShortCut->cAlphaFieldNames(4), + state.dataIPShortCut->cAlphaArgs(4), + Pollution.DieselCoef.COSched, + ErrorsFound); + } + Pollution.DieselCoef.CH4 = state.dataIPShortCut->rNumericArgs(4); + if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Diesel", + state.dataIPShortCut->cAlphaFieldNames(5), + state.dataIPShortCut->cAlphaArgs(5), + Pollution.DieselCoef.CH4Sched, + ErrorsFound); + } + Pollution.DieselCoef.NOx = state.dataIPShortCut->rNumericArgs(5); + if (!state.dataIPShortCut->lAlphaFieldBlanks(6)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Diesel", + state.dataIPShortCut->cAlphaFieldNames(6), + state.dataIPShortCut->cAlphaArgs(6), + Pollution.DieselCoef.NOxSched, + ErrorsFound); + } + Pollution.DieselCoef.N2O = state.dataIPShortCut->rNumericArgs(6); + if (!state.dataIPShortCut->lAlphaFieldBlanks(7)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Diesel", + state.dataIPShortCut->cAlphaFieldNames(7), + state.dataIPShortCut->cAlphaArgs(7), + Pollution.DieselCoef.N2OSched, + ErrorsFound); + } + Pollution.DieselCoef.SO2 = state.dataIPShortCut->rNumericArgs(7); + if (!state.dataIPShortCut->lAlphaFieldBlanks(8)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Diesel", + state.dataIPShortCut->cAlphaFieldNames(8), + state.dataIPShortCut->cAlphaArgs(8), + Pollution.DieselCoef.SO2Sched, + ErrorsFound); + } + Pollution.DieselCoef.PM = state.dataIPShortCut->rNumericArgs(8); + if (!state.dataIPShortCut->lAlphaFieldBlanks(9)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Diesel", + state.dataIPShortCut->cAlphaFieldNames(9), + state.dataIPShortCut->cAlphaArgs(9), + Pollution.DieselCoef.PMSched, + ErrorsFound); + } + Pollution.DieselCoef.PM10 = state.dataIPShortCut->rNumericArgs(9); + if (!state.dataIPShortCut->lAlphaFieldBlanks(10)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Diesel", + state.dataIPShortCut->cAlphaFieldNames(10), + state.dataIPShortCut->cAlphaArgs(10), + Pollution.DieselCoef.PM10Sched, + ErrorsFound); + } + Pollution.DieselCoef.PM25 = state.dataIPShortCut->rNumericArgs(10); + if (!state.dataIPShortCut->lAlphaFieldBlanks(11)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Diesel", + state.dataIPShortCut->cAlphaFieldNames(11), + state.dataIPShortCut->cAlphaArgs(11), + Pollution.DieselCoef.PM25Sched, + ErrorsFound); + } + Pollution.DieselCoef.NH3 = state.dataIPShortCut->rNumericArgs(11); + if (!state.dataIPShortCut->lAlphaFieldBlanks(12)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Diesel", + state.dataIPShortCut->cAlphaFieldNames(12), + state.dataIPShortCut->cAlphaArgs(12), + Pollution.DieselCoef.NH3Sched, + ErrorsFound); + } + Pollution.DieselCoef.NMVOC = state.dataIPShortCut->rNumericArgs(12); + if (!state.dataIPShortCut->lAlphaFieldBlanks(13)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Diesel", + state.dataIPShortCut->cAlphaFieldNames(13), + state.dataIPShortCut->cAlphaArgs(13), + Pollution.DieselCoef.NMVOCSched, + ErrorsFound); + } + Pollution.DieselCoef.Hg = state.dataIPShortCut->rNumericArgs(13); + if (!state.dataIPShortCut->lAlphaFieldBlanks(14)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Diesel", + state.dataIPShortCut->cAlphaFieldNames(14), + state.dataIPShortCut->cAlphaArgs(14), + Pollution.DieselCoef.HgSched, + ErrorsFound); + } + Pollution.DieselCoef.Pb = state.dataIPShortCut->rNumericArgs(14); + if (!state.dataIPShortCut->lAlphaFieldBlanks(15)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Diesel", + state.dataIPShortCut->cAlphaFieldNames(15), + state.dataIPShortCut->cAlphaArgs(15), + Pollution.DieselCoef.PbSched, + ErrorsFound); + } + Pollution.DieselCoef.Water = state.dataIPShortCut->rNumericArgs(15); + if (!state.dataIPShortCut->lAlphaFieldBlanks(16)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Diesel", + state.dataIPShortCut->cAlphaFieldNames(16), + state.dataIPShortCut->cAlphaArgs(16), + Pollution.DieselCoef.WaterSched, + ErrorsFound); + } + Pollution.DieselCoef.NucHi = state.dataIPShortCut->rNumericArgs(16); + if (!state.dataIPShortCut->lAlphaFieldBlanks(17)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Diesel", + state.dataIPShortCut->cAlphaFieldNames(17), + state.dataIPShortCut->cAlphaArgs(17), + Pollution.DieselCoef.NucHiSched, + ErrorsFound); + } + Pollution.DieselCoef.NucLo = state.dataIPShortCut->rNumericArgs(17); + if (!state.dataIPShortCut->lAlphaFieldBlanks(18)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "Diesel", + state.dataIPShortCut->cAlphaFieldNames(18), + state.dataIPShortCut->cAlphaArgs(18), + Pollution.DieselCoef.NucLoSched, + ErrorsFound); + } + } break; + case Constant::eFuel::OtherFuel1: { + if (Pollution.OtherFuel1Coef.FuelFactorUsed) { + ShowWarningError(state, + format("{}: {} already entered. Previous entry will be used.", cCurrentModuleObject, FuelType.FuelTypeNames(Loop))); + continue; + } + Pollution.OtherFuel1Coef.FuelFactorUsed = true; + // OtherFuel1 Coeffs + Pollution.OtherFuel1Coef.Source = state.dataIPShortCut->rNumericArgs(1); + if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel1", + state.dataIPShortCut->cAlphaFieldNames(2), + state.dataIPShortCut->cAlphaArgs(2), + Pollution.OtherFuel1Coef.SourceSched, + ErrorsFound); + } + Pollution.OtherFuel1Coef.CO2 = state.dataIPShortCut->rNumericArgs(2); + if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel1", + state.dataIPShortCut->cAlphaFieldNames(3), + state.dataIPShortCut->cAlphaArgs(3), + Pollution.OtherFuel1Coef.CO2Sched, + ErrorsFound); + } + Pollution.OtherFuel1Coef.CO = state.dataIPShortCut->rNumericArgs(3); + if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel1", + state.dataIPShortCut->cAlphaFieldNames(4), + state.dataIPShortCut->cAlphaArgs(4), + Pollution.OtherFuel1Coef.COSched, + ErrorsFound); + } + Pollution.OtherFuel1Coef.CH4 = state.dataIPShortCut->rNumericArgs(4); + if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel1", + state.dataIPShortCut->cAlphaFieldNames(5), + state.dataIPShortCut->cAlphaArgs(5), + Pollution.OtherFuel1Coef.CH4Sched, + ErrorsFound); + } + Pollution.OtherFuel1Coef.NOx = state.dataIPShortCut->rNumericArgs(5); + if (!state.dataIPShortCut->lAlphaFieldBlanks(6)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel1", + state.dataIPShortCut->cAlphaFieldNames(6), + state.dataIPShortCut->cAlphaArgs(6), + Pollution.OtherFuel1Coef.NOxSched, + ErrorsFound); + } + Pollution.OtherFuel1Coef.N2O = state.dataIPShortCut->rNumericArgs(6); + if (!state.dataIPShortCut->lAlphaFieldBlanks(7)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel1", + state.dataIPShortCut->cAlphaFieldNames(7), + state.dataIPShortCut->cAlphaArgs(7), + Pollution.OtherFuel1Coef.N2OSched, + ErrorsFound); + } + Pollution.OtherFuel1Coef.SO2 = state.dataIPShortCut->rNumericArgs(7); + if (!state.dataIPShortCut->lAlphaFieldBlanks(8)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel1", + state.dataIPShortCut->cAlphaFieldNames(8), + state.dataIPShortCut->cAlphaArgs(8), + Pollution.OtherFuel1Coef.SO2Sched, + ErrorsFound); + } + Pollution.OtherFuel1Coef.PM = state.dataIPShortCut->rNumericArgs(8); + if (!state.dataIPShortCut->lAlphaFieldBlanks(9)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel1", + state.dataIPShortCut->cAlphaFieldNames(9), + state.dataIPShortCut->cAlphaArgs(9), + Pollution.OtherFuel1Coef.PMSched, + ErrorsFound); + } + Pollution.OtherFuel1Coef.PM10 = state.dataIPShortCut->rNumericArgs(9); + if (!state.dataIPShortCut->lAlphaFieldBlanks(10)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel1", + state.dataIPShortCut->cAlphaFieldNames(10), + state.dataIPShortCut->cAlphaArgs(10), + Pollution.OtherFuel1Coef.PM10Sched, + ErrorsFound); + } + Pollution.OtherFuel1Coef.PM25 = state.dataIPShortCut->rNumericArgs(10); + if (!state.dataIPShortCut->lAlphaFieldBlanks(11)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel1", + state.dataIPShortCut->cAlphaFieldNames(11), + state.dataIPShortCut->cAlphaArgs(11), + Pollution.OtherFuel1Coef.PM25Sched, + ErrorsFound); + } + Pollution.OtherFuel1Coef.NH3 = state.dataIPShortCut->rNumericArgs(11); + if (!state.dataIPShortCut->lAlphaFieldBlanks(12)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel1", + state.dataIPShortCut->cAlphaFieldNames(12), + state.dataIPShortCut->cAlphaArgs(12), + Pollution.OtherFuel1Coef.NH3Sched, + ErrorsFound); + } + Pollution.OtherFuel1Coef.NMVOC = state.dataIPShortCut->rNumericArgs(12); + if (!state.dataIPShortCut->lAlphaFieldBlanks(13)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel1", + state.dataIPShortCut->cAlphaFieldNames(13), + state.dataIPShortCut->cAlphaArgs(13), + Pollution.OtherFuel1Coef.NMVOCSched, + ErrorsFound); + } + Pollution.OtherFuel1Coef.Hg = state.dataIPShortCut->rNumericArgs(13); + if (!state.dataIPShortCut->lAlphaFieldBlanks(14)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel1", + state.dataIPShortCut->cAlphaFieldNames(14), + state.dataIPShortCut->cAlphaArgs(14), + Pollution.OtherFuel1Coef.HgSched, + ErrorsFound); + } + Pollution.OtherFuel1Coef.Pb = state.dataIPShortCut->rNumericArgs(14); + if (!state.dataIPShortCut->lAlphaFieldBlanks(15)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel1", + state.dataIPShortCut->cAlphaFieldNames(15), + state.dataIPShortCut->cAlphaArgs(15), + Pollution.OtherFuel1Coef.PbSched, + ErrorsFound); + } + Pollution.OtherFuel1Coef.Water = state.dataIPShortCut->rNumericArgs(15); + if (!state.dataIPShortCut->lAlphaFieldBlanks(16)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel1", + state.dataIPShortCut->cAlphaFieldNames(16), + state.dataIPShortCut->cAlphaArgs(16), + Pollution.OtherFuel1Coef.WaterSched, + ErrorsFound); + } + Pollution.OtherFuel1Coef.NucHi = state.dataIPShortCut->rNumericArgs(16); + if (!state.dataIPShortCut->lAlphaFieldBlanks(17)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel1", + state.dataIPShortCut->cAlphaFieldNames(17), + state.dataIPShortCut->cAlphaArgs(17), + Pollution.OtherFuel1Coef.NucHiSched, + ErrorsFound); + } + Pollution.OtherFuel1Coef.NucLo = state.dataIPShortCut->rNumericArgs(17); + if (!state.dataIPShortCut->lAlphaFieldBlanks(18)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel1", + state.dataIPShortCut->cAlphaFieldNames(18), + state.dataIPShortCut->cAlphaArgs(18), + Pollution.OtherFuel1Coef.NucLoSched, + ErrorsFound); + } + } break; + case Constant::eFuel::OtherFuel2: { + if (Pollution.OtherFuel2Coef.FuelFactorUsed) { + ShowWarningError(state, + format("{}: {} already entered. Previous entry will be used.", cCurrentModuleObject, FuelType.FuelTypeNames(Loop))); + continue; + } + Pollution.OtherFuel2Coef.FuelFactorUsed = true; + // OtherFuel2 Coeffs + Pollution.OtherFuel2Coef.Source = state.dataIPShortCut->rNumericArgs(1); + if (!state.dataIPShortCut->lAlphaFieldBlanks(2)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel2", + state.dataIPShortCut->cAlphaFieldNames(2), + state.dataIPShortCut->cAlphaArgs(2), + Pollution.OtherFuel2Coef.SourceSched, + ErrorsFound); + } + Pollution.OtherFuel2Coef.CO2 = state.dataIPShortCut->rNumericArgs(2); + if (!state.dataIPShortCut->lAlphaFieldBlanks(3)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel2", + state.dataIPShortCut->cAlphaFieldNames(3), + state.dataIPShortCut->cAlphaArgs(3), + Pollution.OtherFuel2Coef.CO2Sched, + ErrorsFound); + } + Pollution.OtherFuel2Coef.CO = state.dataIPShortCut->rNumericArgs(3); + if (!state.dataIPShortCut->lAlphaFieldBlanks(4)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel2", + state.dataIPShortCut->cAlphaFieldNames(4), + state.dataIPShortCut->cAlphaArgs(4), + Pollution.OtherFuel2Coef.COSched, + ErrorsFound); + } + Pollution.OtherFuel2Coef.CH4 = state.dataIPShortCut->rNumericArgs(4); + if (!state.dataIPShortCut->lAlphaFieldBlanks(5)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel2", + state.dataIPShortCut->cAlphaFieldNames(5), + state.dataIPShortCut->cAlphaArgs(5), + Pollution.OtherFuel2Coef.CH4Sched, + ErrorsFound); + } + Pollution.OtherFuel2Coef.NOx = state.dataIPShortCut->rNumericArgs(5); + if (!state.dataIPShortCut->lAlphaFieldBlanks(6)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel2", + state.dataIPShortCut->cAlphaFieldNames(6), + state.dataIPShortCut->cAlphaArgs(6), + Pollution.OtherFuel2Coef.NOxSched, + ErrorsFound); + } + Pollution.OtherFuel2Coef.N2O = state.dataIPShortCut->rNumericArgs(6); + if (!state.dataIPShortCut->lAlphaFieldBlanks(7)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel2", + state.dataIPShortCut->cAlphaFieldNames(7), + state.dataIPShortCut->cAlphaArgs(7), + Pollution.OtherFuel2Coef.N2OSched, + ErrorsFound); + } + Pollution.OtherFuel2Coef.SO2 = state.dataIPShortCut->rNumericArgs(7); + if (!state.dataIPShortCut->lAlphaFieldBlanks(8)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel2", + state.dataIPShortCut->cAlphaFieldNames(8), + state.dataIPShortCut->cAlphaArgs(8), + Pollution.OtherFuel2Coef.SO2Sched, + ErrorsFound); + } + Pollution.OtherFuel2Coef.PM = state.dataIPShortCut->rNumericArgs(8); + if (!state.dataIPShortCut->lAlphaFieldBlanks(9)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel2", + state.dataIPShortCut->cAlphaFieldNames(9), + state.dataIPShortCut->cAlphaArgs(9), + Pollution.OtherFuel2Coef.PMSched, + ErrorsFound); + } + Pollution.OtherFuel2Coef.PM10 = state.dataIPShortCut->rNumericArgs(9); + if (!state.dataIPShortCut->lAlphaFieldBlanks(10)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel2", + state.dataIPShortCut->cAlphaFieldNames(10), + state.dataIPShortCut->cAlphaArgs(10), + Pollution.OtherFuel2Coef.PM10Sched, + ErrorsFound); + } + Pollution.OtherFuel2Coef.PM25 = state.dataIPShortCut->rNumericArgs(10); + if (!state.dataIPShortCut->lAlphaFieldBlanks(11)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel2", + state.dataIPShortCut->cAlphaFieldNames(11), + state.dataIPShortCut->cAlphaArgs(11), + Pollution.OtherFuel2Coef.PM25Sched, + ErrorsFound); + } + Pollution.OtherFuel2Coef.NH3 = state.dataIPShortCut->rNumericArgs(11); + if (!state.dataIPShortCut->lAlphaFieldBlanks(12)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel2", + state.dataIPShortCut->cAlphaFieldNames(12), + state.dataIPShortCut->cAlphaArgs(12), + Pollution.OtherFuel2Coef.NH3Sched, + ErrorsFound); + } + Pollution.OtherFuel2Coef.NMVOC = state.dataIPShortCut->rNumericArgs(12); + if (!state.dataIPShortCut->lAlphaFieldBlanks(13)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel2", + state.dataIPShortCut->cAlphaFieldNames(13), + state.dataIPShortCut->cAlphaArgs(13), + Pollution.OtherFuel2Coef.NMVOCSched, + ErrorsFound); + } + Pollution.OtherFuel2Coef.Hg = state.dataIPShortCut->rNumericArgs(13); + if (!state.dataIPShortCut->lAlphaFieldBlanks(14)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel2", + state.dataIPShortCut->cAlphaFieldNames(14), + state.dataIPShortCut->cAlphaArgs(14), + Pollution.OtherFuel2Coef.HgSched, + ErrorsFound); + } + Pollution.OtherFuel2Coef.Pb = state.dataIPShortCut->rNumericArgs(14); + if (!state.dataIPShortCut->lAlphaFieldBlanks(15)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel2", + state.dataIPShortCut->cAlphaFieldNames(15), + state.dataIPShortCut->cAlphaArgs(15), + Pollution.OtherFuel2Coef.PbSched, + ErrorsFound); + } + Pollution.OtherFuel2Coef.Water = state.dataIPShortCut->rNumericArgs(15); + if (!state.dataIPShortCut->lAlphaFieldBlanks(16)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel2", + state.dataIPShortCut->cAlphaFieldNames(16), + state.dataIPShortCut->cAlphaArgs(16), + Pollution.OtherFuel2Coef.WaterSched, + ErrorsFound); + } + Pollution.OtherFuel2Coef.NucHi = state.dataIPShortCut->rNumericArgs(16); + if (!state.dataIPShortCut->lAlphaFieldBlanks(17)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel2", + state.dataIPShortCut->cAlphaFieldNames(17), + state.dataIPShortCut->cAlphaArgs(17), + Pollution.OtherFuel2Coef.NucHiSched, + ErrorsFound); + } + Pollution.OtherFuel2Coef.NucLo = state.dataIPShortCut->rNumericArgs(17); + if (!state.dataIPShortCut->lAlphaFieldBlanks(18)) { + CheckFFSchedule(state, + cCurrentModuleObject, + "OtherFuel2", + state.dataIPShortCut->cAlphaFieldNames(18), + state.dataIPShortCut->cAlphaArgs(18), + Pollution.OtherFuel2Coef.NucLoSched, + ErrorsFound); + } + } break; + default: { + ShowSevereError(state, format("Illegal FuelType for Pollution Calc Entered={}", FuelType.FuelTypeNames(Loop))); + ErrorsFound = true; + } break; } } // End of the NumEnergyTypes Do Loop @@ -2181,7 +2198,7 @@ void SetupPollutionMeterReporting(EnergyPlusData &state) auto &FuelType = state.dataPollutionModule->FuelType; for (Loop = 1; Loop <= static_cast(PollFactor::Num); ++Loop) { - if (FuelType.FuelTypeNames(Loop).empty()) continue; + // if (FuelType.FuelTypeNames(Loop).empty()) continue; { std::string const &SELECT_CASE_var = FuelType.FuelTypeNames(Loop); diff --git a/src/EnergyPlus/PollutionModule.hh b/src/EnergyPlus/PollutionModule.hh index a2692fee4fa..742d09e7094 100644 --- a/src/EnergyPlus/PollutionModule.hh +++ b/src/EnergyPlus/PollutionModule.hh @@ -53,6 +53,7 @@ // EnergyPlus Headers #include +#include #include #include @@ -343,7 +344,7 @@ namespace PollutionModule { { // Members // FuelType Names - Array1D_string FuelTypeNames; + Array1D FuelTypeNames; // Fuel Types used with the Pollution Factors Real64 Elec; Real64 NatGas; From ebafcf62eba518eedff23c118719136845a1a847 Mon Sep 17 00:00:00 2001 From: Dareum Nam Date: Tue, 30 May 2023 14:10:12 -0600 Subject: [PATCH 02/26] convert to eFuel & replace select_case_vars to switch statement 2 --- src/EnergyPlus/PollutionModule.cc | 4180 ++++++++++++++--------------- 1 file changed, 2085 insertions(+), 2095 deletions(-) diff --git a/src/EnergyPlus/PollutionModule.cc b/src/EnergyPlus/PollutionModule.cc index 0a01fb717a3..1d8d4fe8944 100644 --- a/src/EnergyPlus/PollutionModule.cc +++ b/src/EnergyPlus/PollutionModule.cc @@ -2200,2101 +2200,2091 @@ void SetupPollutionMeterReporting(EnergyPlusData &state) // if (FuelType.FuelTypeNames(Loop).empty()) continue; - { - std::string const &SELECT_CASE_var = FuelType.FuelTypeNames(Loop); - if (SELECT_CASE_var == "NATURALGAS") { - // Pollutants from Natural Gas - SetupOutputVariable(state, - "Environmental Impact NaturalGas Source Energy", - OutputProcessor::Unit::J, - Pollution.NatGasComp.Source, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Source", - "NaturalGasEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact NaturalGas CO2 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.NatGasComp.CO2Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CO2", - "NaturalGasEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact NaturalGas CO Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.NatGasComp.COPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CO", - "NaturalGasEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact NaturalGas CH4 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.NatGasComp.CH4Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CH4", - "NaturalGasEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact NaturalGas NOx Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.NatGasComp.NOxPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NOx", - "NaturalGasEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact NaturalGas N2O Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.NatGasComp.N2OPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "N2O", - "NaturalGasEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact NaturalGas SO2 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.NatGasComp.SO2Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "SO2", - "NaturalGasEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact NaturalGas PM Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.NatGasComp.PMPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM", - "NaturalGasEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact NaturalGas PM10 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.NatGasComp.PM10Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM10", - "NaturalGasEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact NaturalGas PM2.5 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.NatGasComp.PM25Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM2.5", - "NaturalGasEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact NaturalGas NH3 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.NatGasComp.NH3Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NH3", - "NaturalGasEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact NaturalGas NMVOC Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.NatGasComp.NMVOCPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NMVOC", - "NaturalGasEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact NaturalGas Hg Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.NatGasComp.HgPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Hg", - "NaturalGasEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact NaturalGas Pb Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.NatGasComp.PbPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Pb", - "NaturalGasEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact NaturalGas Water Consumption Volume", - OutputProcessor::Unit::L, - Pollution.NatGasComp.WaterPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "WaterEnvironmentalFactors", - "NaturalGasEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact NaturalGas Nuclear High Level Waste Mass", - OutputProcessor::Unit::kg, - Pollution.NatGasComp.NucHiPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Nuclear High", - "NaturalGasEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact NaturalGas Nuclear Low Level Waste Volume", - OutputProcessor::Unit::m3, - Pollution.NatGasComp.NucLoPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Nuclear Low", - "NaturalGasEmissions", - {}, - ""); - - } else if (SELECT_CASE_var == "FUELOILNO2") { - // Pollutants from FuelOilNo2 - SetupOutputVariable(state, - "Environmental Impact FuelOilNo2 Source Energy", - OutputProcessor::Unit::J, - Pollution.FuelOil2Comp.Source, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Source", - "FuelOilNo2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo2 CO2 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil2Comp.CO2Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CO2", - "FuelOilNo2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo2 CO Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil2Comp.COPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CO", - "FuelOilNo2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo2 CH4 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil2Comp.CH4Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CH4", - "FuelOilNo2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo2 NOx Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil2Comp.NOxPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NOx", - "FuelOilNo2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo2 N2O Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil2Comp.N2OPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "N2O", - "FuelOilNo2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo2 SO2 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil2Comp.SO2Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "SO2", - "FuelOilNo2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo2 PM Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil2Comp.PMPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM", - "FuelOilNo2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo2 PM10 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil2Comp.PM10Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM10", - "FuelOilNo2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo2 PM2.5 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil2Comp.PM25Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM2.5", - "FuelOilNo2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo2 NH3 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil2Comp.NH3Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NH3", - "FuelOilNo2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo2 NMVOC Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil2Comp.NMVOCPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NMVOC", - "FuelOilNo2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo2 Hg Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil2Comp.HgPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Hg", - "FuelOilNo2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo2 Pb Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil2Comp.PbPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Pb", - "FuelOilNo2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo2 Water Consumption Volume", - OutputProcessor::Unit::L, - Pollution.FuelOil2Comp.WaterPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "WaterEnvironmentalFactors", - "FuelOilNo2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo2 Nuclear High Level Waste Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil2Comp.NucHiPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Nuclear High", - "FuelOilNo2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo2 Nuclear Low Level Waste Volume", - OutputProcessor::Unit::m3, - Pollution.FuelOil2Comp.NucLoPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Nuclear Low", - "FuelOilNo2Emissions", - {}, - ""); - - } else if (SELECT_CASE_var == "FUELOILNO1") { - // Pollutants from FuelOilNo1 - SetupOutputVariable(state, - "Environmental Impact FuelOilNo1 Source Energy", - OutputProcessor::Unit::J, - Pollution.FuelOil1Comp.Source, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Source", - "FuelOilNo1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo1 CO2 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil1Comp.CO2Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CO2", - "FuelOilNo1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo1 CO Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil1Comp.COPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CO", - "FuelOilNo1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo1 CH4 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil1Comp.CH4Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CH4", - "FuelOilNo1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo1 NOx Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil1Comp.NOxPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NOx", - "FuelOilNo1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo1 N2O Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil1Comp.N2OPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "N2O", - "FuelOilNo1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo1 SO2 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil1Comp.SO2Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "SO2", - "FuelOilNo1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo1 PM Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil1Comp.PMPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM", - "FuelOilNo1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo1 PM10 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil1Comp.PM10Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM10", - "FuelOilNo1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo1 PM2.5 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil1Comp.PM25Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM2.5", - "FuelOilNo1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo1 NH3 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil1Comp.NH3Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NH3", - "FuelOilNo1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo1 NMVOC Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil1Comp.NMVOCPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NMVOC", - "FuelOilNo1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo1 Hg Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil1Comp.HgPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Hg", - "FuelOilNo1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo1 Pb Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil1Comp.PbPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Pb", - "FuelOilNo1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo1 Water Consumption Volume", - OutputProcessor::Unit::L, - Pollution.FuelOil1Comp.WaterPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "WaterEnvironmentalFactors", - "FuelOilNo1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo1 Nuclear High Level Waste Mass", - OutputProcessor::Unit::kg, - Pollution.FuelOil1Comp.NucHiPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Nuclear High", - "FuelOilNo1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact FuelOilNo1 Nuclear Low Level Waste Volume", - OutputProcessor::Unit::m3, - Pollution.FuelOil1Comp.NucLoPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Nuclear Low", - "FuelOilNo1Emissions", - {}, - ""); - - } else if (SELECT_CASE_var == "COAL") { - // Pollutants from Coal - SetupOutputVariable(state, - "Environmental Impact Coal Source Energy", - OutputProcessor::Unit::J, - Pollution.CoalComp.Source, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Source", - "CoalEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Coal CO2 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.CoalComp.CO2Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CO2", - "CoalEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Coal CO Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.CoalComp.COPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CO", - "CoalEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Coal CH4 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.CoalComp.CH4Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CH4", - "CoalEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Coal NOx Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.CoalComp.NOxPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NOx", - "CoalEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Coal N2O Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.CoalComp.N2OPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "N2O", - "CoalEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Coal SO2 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.CoalComp.SO2Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "SO2", - "CoalEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Coal PM Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.CoalComp.PMPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM", - "CoalEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Coal PM10 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.CoalComp.PM10Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM10", - "CoalEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Coal PM2.5 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.CoalComp.PM25Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM2.5", - "CoalEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Coal NH3 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.CoalComp.NH3Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NH3", - "CoalEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Coal NMVOC Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.CoalComp.NMVOCPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NMVOC", - "CoalEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Coal Hg Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.CoalComp.HgPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Hg", - "CoalEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Coal Pb Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.CoalComp.PbPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Pb", - "CoalEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Coal Water Consumption Volume", - OutputProcessor::Unit::L, - Pollution.CoalComp.WaterPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "WaterEnvironmentalFactors", - "CoalEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Coal Nuclear High Level Waste Mass", - OutputProcessor::Unit::kg, - Pollution.CoalComp.NucHiPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Nuclear High", - "CoalEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Coal Nuclear Low Level Waste Volume", - OutputProcessor::Unit::m3, - Pollution.CoalComp.NucLoPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Nuclear Low", - "CoalEmissions", - {}, - ""); - - } else if (SELECT_CASE_var == "ELECTRICITY") { - // Pollutants from Electricity - SetupOutputVariable(state, - "Environmental Impact Electricity Source Energy", - OutputProcessor::Unit::J, - Pollution.ElecComp.Source, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Source", - "ElectricityEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Electricity CO2 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.ElecComp.CO2Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CO2", - "ElectricityEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Electricity CO Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.ElecComp.COPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CO", - "ElectricityEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Electricity CH4 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.ElecComp.CH4Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CH4", - "ElectricityEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Electricity NOx Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.ElecComp.NOxPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NOx", - "ElectricityEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Electricity N2O Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.ElecComp.N2OPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "N2O", - "ElectricityEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Electricity SO2 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.ElecComp.SO2Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "SO2", - "ElectricityEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Electricity PM Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.ElecComp.PMPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM", - "ElectricityEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Electricity PM10 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.ElecComp.PM10Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM10", - "ElectricityEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Electricity PM2.5 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.ElecComp.PM25Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM2.5", - "ElectricityEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Electricity NH3 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.ElecComp.NH3Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NH3", - "ElectricityEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Electricity NMVOC Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.ElecComp.NMVOCPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NMVOC", - "ElectricityEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Electricity Hg Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.ElecComp.HgPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Hg", - "ElectricityEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Electricity Pb Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.ElecComp.PbPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Pb", - "ElectricityEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Electricity Water Consumption Volume", - OutputProcessor::Unit::L, - Pollution.ElecComp.WaterPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "WaterEnvironmentalFactors", - "ElectricityEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Electricity Nuclear High Level Waste Mass", - OutputProcessor::Unit::kg, - Pollution.ElecComp.NucHiPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Nuclear High", - "ElectricityEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Electricity Nuclear Low Level Waste Volume", - OutputProcessor::Unit::m3, - Pollution.ElecComp.NucLoPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Nuclear Low", - "ElectricityEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Purchased Electricity Source Energy", - OutputProcessor::Unit::J, - Pollution.ElecPurchComp.Source, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Source", - "PurchasedElectricityEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Surplus Sold Electricity Source", - OutputProcessor::Unit::J, - Pollution.ElecSurplusSoldComp.Source, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Source", - "SoldElectricityEmissions", - {}, - ""); - } else if (SELECT_CASE_var == "GASOLINE") { - // Pollutants from Gasoline - SetupOutputVariable(state, - "Environmental Impact Gasoline Source Energy", - OutputProcessor::Unit::J, - Pollution.GasolineComp.Source, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Source", - "GasolineEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Gasoline CO2 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.GasolineComp.CO2Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CO2", - "GasolineEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Gasoline CO Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.GasolineComp.COPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CO", - "GasolineEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Gasoline CH4 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.GasolineComp.CH4Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CH4", - "GasolineEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Gasoline NOx Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.GasolineComp.NOxPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NOx", - "GasolineEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Gasoline N2O Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.GasolineComp.N2OPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "N2O", - "GasolineEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Gasoline SO2 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.GasolineComp.SO2Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "SO2", - "GasolineEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Gasoline PM Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.GasolineComp.PMPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM", - "GasolineEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Gasoline PM10 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.GasolineComp.PM10Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM10", - "GasolineEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Gasoline PM2.5 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.GasolineComp.PM25Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM2.5", - "GasolineEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Gasoline NH3 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.GasolineComp.NH3Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NH3", - "GasolineEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Gasoline NMVOC Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.GasolineComp.NMVOCPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NMVOC", - "GasolineEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Gasoline Hg Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.GasolineComp.HgPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Hg", - "GasolineEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Gasoline Pb Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.GasolineComp.PbPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Pb", - "GasolineEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Gasoline Water Consumption Volume", - OutputProcessor::Unit::L, - Pollution.GasolineComp.WaterPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "WaterEnvironmentalFactors", - "GasolineEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Gasoline Nuclear High Level Waste Mass", - OutputProcessor::Unit::kg, - Pollution.GasolineComp.NucHiPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Nuclear High", - "GasolineEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Gasoline Nuclear Low Level Waste Volume", - OutputProcessor::Unit::m3, - Pollution.GasolineComp.NucLoPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Nuclear Low", - "GasolineEmissions", - {}, - ""); - - } else if (SELECT_CASE_var == "PROPANE") { - // Pollutants from Propane - SetupOutputVariable(state, - "Environmental Impact Propane Source Energy", - OutputProcessor::Unit::J, - Pollution.PropaneComp.Source, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Source", - "PropaneEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Propane CO2 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.PropaneComp.CO2Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CO2", - "PropaneEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Propane CO Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.PropaneComp.COPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CO", - "PropaneEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Propane CH4 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.PropaneComp.CH4Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CH4", - "PropaneEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Propane NOx Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.PropaneComp.NOxPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NOx", - "PropaneEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Propane N2O Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.PropaneComp.N2OPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "N2O", - "PropaneEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Propane SO2 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.PropaneComp.SO2Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "SO2", - "PropaneEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Propane PM Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.PropaneComp.PMPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM", - "PropaneEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Propane PM10 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.PropaneComp.PM10Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM10", - "PropaneEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Propane PM2.5 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.PropaneComp.PM25Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM2.5", - "PropaneEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Propane NH3 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.PropaneComp.NH3Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NH3", - "PropaneEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Propane NMVOC Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.PropaneComp.NMVOCPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NMVOC", - "PropaneEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Propane Hg Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.PropaneComp.HgPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Hg", - "PropaneEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Propane Pb Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.PropaneComp.PbPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Pb", - "PropaneEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Propane Water Consumption Volume", - OutputProcessor::Unit::L, - Pollution.PropaneComp.WaterPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "WaterEnvironmentalFactors", - "PropaneEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Propane Nuclear High Level Waste Mass", - OutputProcessor::Unit::kg, - Pollution.PropaneComp.NucHiPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Nuclear High", - "PropaneEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Propane Nuclear Low Level Waste Volume", - OutputProcessor::Unit::m3, - Pollution.PropaneComp.NucLoPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Nuclear Low", - "PropaneEmissions", - {}, - ""); - - } else if (SELECT_CASE_var == "DIESEL") { - // Pollutants from Diesel - SetupOutputVariable(state, - "Environmental Impact Diesel Source Energy", - OutputProcessor::Unit::J, - Pollution.DieselComp.Source, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Source", - "DieselEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Diesel CO2 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.DieselComp.CO2Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CO2", - "DieselEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Diesel CO Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.DieselComp.COPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CO", - "DieselEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Diesel CH4 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.DieselComp.CH4Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CH4", - "DieselEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Diesel NOx Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.DieselComp.NOxPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NOx", - "DieselEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Diesel N2O Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.DieselComp.N2OPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "N2O", - "DieselEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Diesel SO2 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.DieselComp.SO2Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "SO2", - "DieselEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Diesel PM Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.DieselComp.PMPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM", - "DieselEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Diesel PM10 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.DieselComp.PM10Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM10", - "DieselEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Diesel PM2.5 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.DieselComp.PM25Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM2.5", - "DieselEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Diesel NH3 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.DieselComp.NH3Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NH3", - "DieselEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Diesel NMVOC Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.DieselComp.NMVOCPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NMVOC", - "DieselEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Diesel Hg Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.DieselComp.HgPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Hg", - "DieselEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Diesel Pb Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.DieselComp.PbPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Pb", - "DieselEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Diesel Water Consumption Volume", - OutputProcessor::Unit::L, - Pollution.DieselComp.WaterPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "WaterEnvironmentalFactors", - "DieselEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Diesel Nuclear High Level Waste Mass", - OutputProcessor::Unit::kg, - Pollution.DieselComp.NucHiPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Nuclear High", - "DieselEmissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact Diesel Nuclear Low Level Waste Volume", - OutputProcessor::Unit::m3, - Pollution.DieselComp.NucLoPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Nuclear Low", - "DieselEmissions", - {}, - ""); - - } else if (SELECT_CASE_var == "OTHERFUEL1") { - // Pollutants from OtherFuel1 - SetupOutputVariable(state, - "Environmental Impact OtherFuel1 Source Energy", - OutputProcessor::Unit::J, - Pollution.OtherFuel1Comp.Source, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Source", - "OtherFuel1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel1 CO2 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel1Comp.CO2Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CO2", - "OtherFuel1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel1 CO Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel1Comp.COPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CO", - "OtherFuel1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel1 CH4 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel1Comp.CH4Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CH4", - "OtherFuel1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel1 NOx Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel1Comp.NOxPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NOx", - "OtherFuel1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel1 N2O Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel1Comp.N2OPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "N2O", - "OtherFuel1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel1 SO2 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel1Comp.SO2Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "SO2", - "OtherFuel1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel1 PM Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel1Comp.PMPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM", - "OtherFuel1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel1 PM10 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel1Comp.PM10Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM10", - "OtherFuel1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel1 PM2.5 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel1Comp.PM25Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM2.5", - "OtherFuel1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel1 NH3 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel1Comp.NH3Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NH3", - "OtherFuel1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel1 NMVOC Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel1Comp.NMVOCPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NMVOC", - "OtherFuel1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel1 Hg Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel1Comp.HgPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Hg", - "OtherFuel1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel1 Pb Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel1Comp.PbPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Pb", - "OtherFuel1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel1 Water Consumption Volume", - OutputProcessor::Unit::L, - Pollution.OtherFuel1Comp.WaterPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "WaterEnvironmentalFactors", - "OtherFuel1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel1 Nuclear High Level Waste Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel1Comp.NucHiPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Nuclear High", - "OtherFuel1Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel1 Nuclear Low Level Waste Volume", - OutputProcessor::Unit::m3, - Pollution.OtherFuel1Comp.NucLoPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Nuclear Low", - "OtherFuel1Emissions", - {}, - ""); - - } else if (SELECT_CASE_var == "OTHERFUEL2") { - // Pollutants from OtherFuel2 - SetupOutputVariable(state, - "Environmental Impact OtherFuel2 Source Energy", - OutputProcessor::Unit::J, - Pollution.OtherFuel2Comp.Source, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Source", - "OtherFuel2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel2 CO2 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel2Comp.CO2Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CO2", - "OtherFuel2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel2 CO Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel2Comp.COPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CO", - "OtherFuel2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel2 CH4 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel2Comp.CH4Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "CH4", - "OtherFuel2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel2 NOx Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel2Comp.NOxPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NOx", - "OtherFuel2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel2 N2O Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel2Comp.N2OPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "N2O", - "OtherFuel2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel2 SO2 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel2Comp.SO2Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "SO2", - "OtherFuel2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel2 PM Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel2Comp.PMPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM", - "OtherFuel2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel2 PM10 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel2Comp.PM10Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM10", - "OtherFuel2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel2 PM2.5 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel2Comp.PM25Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "PM2.5", - "OtherFuel2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel2 NH3 Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel2Comp.NH3Pollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NH3", - "OtherFuel2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel2 NMVOC Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel2Comp.NMVOCPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "NMVOC", - "OtherFuel2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel2 Hg Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel2Comp.HgPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Hg", - "OtherFuel2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel2 Pb Emissions Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel2Comp.PbPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Pb", - "OtherFuel2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel2 Water Consumption Volume", - OutputProcessor::Unit::L, - Pollution.OtherFuel2Comp.WaterPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "WaterEnvironmentalFactors", - "OtherFuel2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel2 Nuclear High Level Waste Mass", - OutputProcessor::Unit::kg, - Pollution.OtherFuel2Comp.NucHiPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Nuclear High", - "OtherFuel2Emissions", - {}, - ""); - SetupOutputVariable(state, - "Environmental Impact OtherFuel2 Nuclear Low Level Waste Volume", - OutputProcessor::Unit::m3, - Pollution.OtherFuel2Comp.NucLoPollution, - OutputProcessor::SOVTimeStepType::System, - OutputProcessor::SOVStoreType::Summed, - "Site", - {}, - "Nuclear Low", - "OtherFuel2Emissions", - {}, - ""); - } + switch (FuelType.FuelTypeNames(Loop)) { + case Constant::eFuel::NaturalGas: { // Pollutants from Natural Gas + SetupOutputVariable(state, + "Environmental Impact NaturalGas Source Energy", + OutputProcessor::Unit::J, + Pollution.NatGasComp.Source, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Source", + "NaturalGasEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact NaturalGas CO2 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.NatGasComp.CO2Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CO2", + "NaturalGasEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact NaturalGas CO Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.NatGasComp.COPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CO", + "NaturalGasEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact NaturalGas CH4 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.NatGasComp.CH4Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CH4", + "NaturalGasEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact NaturalGas NOx Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.NatGasComp.NOxPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NOx", + "NaturalGasEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact NaturalGas N2O Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.NatGasComp.N2OPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "N2O", + "NaturalGasEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact NaturalGas SO2 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.NatGasComp.SO2Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "SO2", + "NaturalGasEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact NaturalGas PM Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.NatGasComp.PMPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM", + "NaturalGasEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact NaturalGas PM10 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.NatGasComp.PM10Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM10", + "NaturalGasEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact NaturalGas PM2.5 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.NatGasComp.PM25Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM2.5", + "NaturalGasEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact NaturalGas NH3 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.NatGasComp.NH3Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NH3", + "NaturalGasEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact NaturalGas NMVOC Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.NatGasComp.NMVOCPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NMVOC", + "NaturalGasEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact NaturalGas Hg Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.NatGasComp.HgPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Hg", + "NaturalGasEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact NaturalGas Pb Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.NatGasComp.PbPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Pb", + "NaturalGasEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact NaturalGas Water Consumption Volume", + OutputProcessor::Unit::L, + Pollution.NatGasComp.WaterPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "WaterEnvironmentalFactors", + "NaturalGasEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact NaturalGas Nuclear High Level Waste Mass", + OutputProcessor::Unit::kg, + Pollution.NatGasComp.NucHiPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Nuclear High", + "NaturalGasEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact NaturalGas Nuclear Low Level Waste Volume", + OutputProcessor::Unit::m3, + Pollution.NatGasComp.NucLoPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Nuclear Low", + "NaturalGasEmissions", + {}, + ""); + } break; + case Constant::eFuel::FuelOilNo2: { // Pollutants from FuelOilNo2 + SetupOutputVariable(state, + "Environmental Impact FuelOilNo2 Source Energy", + OutputProcessor::Unit::J, + Pollution.FuelOil2Comp.Source, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Source", + "FuelOilNo2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo2 CO2 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil2Comp.CO2Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CO2", + "FuelOilNo2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo2 CO Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil2Comp.COPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CO", + "FuelOilNo2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo2 CH4 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil2Comp.CH4Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CH4", + "FuelOilNo2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo2 NOx Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil2Comp.NOxPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NOx", + "FuelOilNo2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo2 N2O Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil2Comp.N2OPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "N2O", + "FuelOilNo2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo2 SO2 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil2Comp.SO2Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "SO2", + "FuelOilNo2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo2 PM Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil2Comp.PMPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM", + "FuelOilNo2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo2 PM10 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil2Comp.PM10Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM10", + "FuelOilNo2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo2 PM2.5 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil2Comp.PM25Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM2.5", + "FuelOilNo2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo2 NH3 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil2Comp.NH3Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NH3", + "FuelOilNo2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo2 NMVOC Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil2Comp.NMVOCPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NMVOC", + "FuelOilNo2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo2 Hg Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil2Comp.HgPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Hg", + "FuelOilNo2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo2 Pb Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil2Comp.PbPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Pb", + "FuelOilNo2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo2 Water Consumption Volume", + OutputProcessor::Unit::L, + Pollution.FuelOil2Comp.WaterPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "WaterEnvironmentalFactors", + "FuelOilNo2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo2 Nuclear High Level Waste Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil2Comp.NucHiPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Nuclear High", + "FuelOilNo2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo2 Nuclear Low Level Waste Volume", + OutputProcessor::Unit::m3, + Pollution.FuelOil2Comp.NucLoPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Nuclear Low", + "FuelOilNo2Emissions", + {}, + ""); + } break; + case Constant::eFuel::FuelOilNo1: { // Pollutants from FuelOilNo1 + SetupOutputVariable(state, + "Environmental Impact FuelOilNo1 Source Energy", + OutputProcessor::Unit::J, + Pollution.FuelOil1Comp.Source, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Source", + "FuelOilNo1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo1 CO2 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil1Comp.CO2Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CO2", + "FuelOilNo1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo1 CO Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil1Comp.COPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CO", + "FuelOilNo1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo1 CH4 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil1Comp.CH4Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CH4", + "FuelOilNo1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo1 NOx Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil1Comp.NOxPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NOx", + "FuelOilNo1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo1 N2O Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil1Comp.N2OPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "N2O", + "FuelOilNo1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo1 SO2 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil1Comp.SO2Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "SO2", + "FuelOilNo1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo1 PM Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil1Comp.PMPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM", + "FuelOilNo1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo1 PM10 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil1Comp.PM10Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM10", + "FuelOilNo1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo1 PM2.5 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil1Comp.PM25Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM2.5", + "FuelOilNo1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo1 NH3 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil1Comp.NH3Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NH3", + "FuelOilNo1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo1 NMVOC Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil1Comp.NMVOCPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NMVOC", + "FuelOilNo1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo1 Hg Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil1Comp.HgPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Hg", + "FuelOilNo1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo1 Pb Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil1Comp.PbPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Pb", + "FuelOilNo1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo1 Water Consumption Volume", + OutputProcessor::Unit::L, + Pollution.FuelOil1Comp.WaterPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "WaterEnvironmentalFactors", + "FuelOilNo1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo1 Nuclear High Level Waste Mass", + OutputProcessor::Unit::kg, + Pollution.FuelOil1Comp.NucHiPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Nuclear High", + "FuelOilNo1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact FuelOilNo1 Nuclear Low Level Waste Volume", + OutputProcessor::Unit::m3, + Pollution.FuelOil1Comp.NucLoPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Nuclear Low", + "FuelOilNo1Emissions", + {}, + ""); + } break; + case Constant::eFuel::Coal: { // Pollutants from Coal + SetupOutputVariable(state, + "Environmental Impact Coal Source Energy", + OutputProcessor::Unit::J, + Pollution.CoalComp.Source, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Source", + "CoalEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Coal CO2 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.CoalComp.CO2Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CO2", + "CoalEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Coal CO Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.CoalComp.COPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CO", + "CoalEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Coal CH4 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.CoalComp.CH4Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CH4", + "CoalEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Coal NOx Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.CoalComp.NOxPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NOx", + "CoalEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Coal N2O Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.CoalComp.N2OPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "N2O", + "CoalEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Coal SO2 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.CoalComp.SO2Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "SO2", + "CoalEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Coal PM Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.CoalComp.PMPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM", + "CoalEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Coal PM10 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.CoalComp.PM10Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM10", + "CoalEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Coal PM2.5 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.CoalComp.PM25Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM2.5", + "CoalEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Coal NH3 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.CoalComp.NH3Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NH3", + "CoalEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Coal NMVOC Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.CoalComp.NMVOCPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NMVOC", + "CoalEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Coal Hg Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.CoalComp.HgPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Hg", + "CoalEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Coal Pb Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.CoalComp.PbPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Pb", + "CoalEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Coal Water Consumption Volume", + OutputProcessor::Unit::L, + Pollution.CoalComp.WaterPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "WaterEnvironmentalFactors", + "CoalEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Coal Nuclear High Level Waste Mass", + OutputProcessor::Unit::kg, + Pollution.CoalComp.NucHiPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Nuclear High", + "CoalEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Coal Nuclear Low Level Waste Volume", + OutputProcessor::Unit::m3, + Pollution.CoalComp.NucLoPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Nuclear Low", + "CoalEmissions", + {}, + ""); + } break; + case Constant::eFuel::Electricity: { // Pollutants from Electricity + SetupOutputVariable(state, + "Environmental Impact Electricity Source Energy", + OutputProcessor::Unit::J, + Pollution.ElecComp.Source, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Source", + "ElectricityEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Electricity CO2 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.ElecComp.CO2Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CO2", + "ElectricityEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Electricity CO Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.ElecComp.COPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CO", + "ElectricityEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Electricity CH4 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.ElecComp.CH4Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CH4", + "ElectricityEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Electricity NOx Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.ElecComp.NOxPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NOx", + "ElectricityEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Electricity N2O Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.ElecComp.N2OPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "N2O", + "ElectricityEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Electricity SO2 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.ElecComp.SO2Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "SO2", + "ElectricityEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Electricity PM Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.ElecComp.PMPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM", + "ElectricityEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Electricity PM10 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.ElecComp.PM10Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM10", + "ElectricityEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Electricity PM2.5 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.ElecComp.PM25Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM2.5", + "ElectricityEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Electricity NH3 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.ElecComp.NH3Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NH3", + "ElectricityEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Electricity NMVOC Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.ElecComp.NMVOCPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NMVOC", + "ElectricityEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Electricity Hg Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.ElecComp.HgPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Hg", + "ElectricityEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Electricity Pb Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.ElecComp.PbPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Pb", + "ElectricityEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Electricity Water Consumption Volume", + OutputProcessor::Unit::L, + Pollution.ElecComp.WaterPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "WaterEnvironmentalFactors", + "ElectricityEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Electricity Nuclear High Level Waste Mass", + OutputProcessor::Unit::kg, + Pollution.ElecComp.NucHiPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Nuclear High", + "ElectricityEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Electricity Nuclear Low Level Waste Volume", + OutputProcessor::Unit::m3, + Pollution.ElecComp.NucLoPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Nuclear Low", + "ElectricityEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Purchased Electricity Source Energy", + OutputProcessor::Unit::J, + Pollution.ElecPurchComp.Source, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Source", + "PurchasedElectricityEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Surplus Sold Electricity Source", + OutputProcessor::Unit::J, + Pollution.ElecSurplusSoldComp.Source, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Source", + "SoldElectricityEmissions", + {}, + ""); + } break; + case Constant::eFuel::Gasoline: { // Pollutants from Gasoline + SetupOutputVariable(state, + "Environmental Impact Gasoline Source Energy", + OutputProcessor::Unit::J, + Pollution.GasolineComp.Source, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Source", + "GasolineEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Gasoline CO2 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.GasolineComp.CO2Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CO2", + "GasolineEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Gasoline CO Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.GasolineComp.COPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CO", + "GasolineEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Gasoline CH4 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.GasolineComp.CH4Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CH4", + "GasolineEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Gasoline NOx Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.GasolineComp.NOxPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NOx", + "GasolineEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Gasoline N2O Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.GasolineComp.N2OPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "N2O", + "GasolineEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Gasoline SO2 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.GasolineComp.SO2Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "SO2", + "GasolineEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Gasoline PM Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.GasolineComp.PMPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM", + "GasolineEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Gasoline PM10 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.GasolineComp.PM10Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM10", + "GasolineEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Gasoline PM2.5 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.GasolineComp.PM25Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM2.5", + "GasolineEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Gasoline NH3 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.GasolineComp.NH3Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NH3", + "GasolineEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Gasoline NMVOC Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.GasolineComp.NMVOCPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NMVOC", + "GasolineEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Gasoline Hg Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.GasolineComp.HgPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Hg", + "GasolineEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Gasoline Pb Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.GasolineComp.PbPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Pb", + "GasolineEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Gasoline Water Consumption Volume", + OutputProcessor::Unit::L, + Pollution.GasolineComp.WaterPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "WaterEnvironmentalFactors", + "GasolineEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Gasoline Nuclear High Level Waste Mass", + OutputProcessor::Unit::kg, + Pollution.GasolineComp.NucHiPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Nuclear High", + "GasolineEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Gasoline Nuclear Low Level Waste Volume", + OutputProcessor::Unit::m3, + Pollution.GasolineComp.NucLoPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Nuclear Low", + "GasolineEmissions", + {}, + ""); + } break; + case Constant::eFuel::Propane: { // Pollutants from Propane + SetupOutputVariable(state, + "Environmental Impact Propane Source Energy", + OutputProcessor::Unit::J, + Pollution.PropaneComp.Source, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Source", + "PropaneEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Propane CO2 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.PropaneComp.CO2Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CO2", + "PropaneEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Propane CO Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.PropaneComp.COPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CO", + "PropaneEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Propane CH4 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.PropaneComp.CH4Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CH4", + "PropaneEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Propane NOx Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.PropaneComp.NOxPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NOx", + "PropaneEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Propane N2O Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.PropaneComp.N2OPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "N2O", + "PropaneEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Propane SO2 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.PropaneComp.SO2Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "SO2", + "PropaneEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Propane PM Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.PropaneComp.PMPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM", + "PropaneEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Propane PM10 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.PropaneComp.PM10Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM10", + "PropaneEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Propane PM2.5 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.PropaneComp.PM25Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM2.5", + "PropaneEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Propane NH3 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.PropaneComp.NH3Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NH3", + "PropaneEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Propane NMVOC Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.PropaneComp.NMVOCPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NMVOC", + "PropaneEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Propane Hg Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.PropaneComp.HgPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Hg", + "PropaneEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Propane Pb Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.PropaneComp.PbPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Pb", + "PropaneEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Propane Water Consumption Volume", + OutputProcessor::Unit::L, + Pollution.PropaneComp.WaterPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "WaterEnvironmentalFactors", + "PropaneEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Propane Nuclear High Level Waste Mass", + OutputProcessor::Unit::kg, + Pollution.PropaneComp.NucHiPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Nuclear High", + "PropaneEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Propane Nuclear Low Level Waste Volume", + OutputProcessor::Unit::m3, + Pollution.PropaneComp.NucLoPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Nuclear Low", + "PropaneEmissions", + {}, + ""); + } break; + case Constant::eFuel::Diesel: { // Pollutants from Diesel + SetupOutputVariable(state, + "Environmental Impact Diesel Source Energy", + OutputProcessor::Unit::J, + Pollution.DieselComp.Source, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Source", + "DieselEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Diesel CO2 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.DieselComp.CO2Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CO2", + "DieselEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Diesel CO Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.DieselComp.COPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CO", + "DieselEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Diesel CH4 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.DieselComp.CH4Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CH4", + "DieselEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Diesel NOx Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.DieselComp.NOxPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NOx", + "DieselEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Diesel N2O Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.DieselComp.N2OPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "N2O", + "DieselEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Diesel SO2 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.DieselComp.SO2Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "SO2", + "DieselEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Diesel PM Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.DieselComp.PMPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM", + "DieselEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Diesel PM10 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.DieselComp.PM10Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM10", + "DieselEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Diesel PM2.5 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.DieselComp.PM25Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM2.5", + "DieselEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Diesel NH3 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.DieselComp.NH3Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NH3", + "DieselEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Diesel NMVOC Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.DieselComp.NMVOCPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NMVOC", + "DieselEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Diesel Hg Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.DieselComp.HgPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Hg", + "DieselEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Diesel Pb Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.DieselComp.PbPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Pb", + "DieselEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Diesel Water Consumption Volume", + OutputProcessor::Unit::L, + Pollution.DieselComp.WaterPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "WaterEnvironmentalFactors", + "DieselEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Diesel Nuclear High Level Waste Mass", + OutputProcessor::Unit::kg, + Pollution.DieselComp.NucHiPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Nuclear High", + "DieselEmissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact Diesel Nuclear Low Level Waste Volume", + OutputProcessor::Unit::m3, + Pollution.DieselComp.NucLoPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Nuclear Low", + "DieselEmissions", + {}, + ""); + } break; + case Constant::eFuel::OtherFuel1: { // Pollutants from OtherFuel1 + SetupOutputVariable(state, + "Environmental Impact OtherFuel1 Source Energy", + OutputProcessor::Unit::J, + Pollution.OtherFuel1Comp.Source, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Source", + "OtherFuel1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel1 CO2 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel1Comp.CO2Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CO2", + "OtherFuel1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel1 CO Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel1Comp.COPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CO", + "OtherFuel1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel1 CH4 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel1Comp.CH4Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CH4", + "OtherFuel1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel1 NOx Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel1Comp.NOxPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NOx", + "OtherFuel1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel1 N2O Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel1Comp.N2OPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "N2O", + "OtherFuel1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel1 SO2 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel1Comp.SO2Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "SO2", + "OtherFuel1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel1 PM Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel1Comp.PMPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM", + "OtherFuel1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel1 PM10 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel1Comp.PM10Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM10", + "OtherFuel1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel1 PM2.5 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel1Comp.PM25Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM2.5", + "OtherFuel1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel1 NH3 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel1Comp.NH3Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NH3", + "OtherFuel1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel1 NMVOC Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel1Comp.NMVOCPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NMVOC", + "OtherFuel1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel1 Hg Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel1Comp.HgPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Hg", + "OtherFuel1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel1 Pb Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel1Comp.PbPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Pb", + "OtherFuel1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel1 Water Consumption Volume", + OutputProcessor::Unit::L, + Pollution.OtherFuel1Comp.WaterPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "WaterEnvironmentalFactors", + "OtherFuel1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel1 Nuclear High Level Waste Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel1Comp.NucHiPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Nuclear High", + "OtherFuel1Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel1 Nuclear Low Level Waste Volume", + OutputProcessor::Unit::m3, + Pollution.OtherFuel1Comp.NucLoPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Nuclear Low", + "OtherFuel1Emissions", + {}, + ""); + } break; + case Constant::eFuel::OtherFuel2: { // Pollutants from OtherFuel2 + SetupOutputVariable(state, + "Environmental Impact OtherFuel2 Source Energy", + OutputProcessor::Unit::J, + Pollution.OtherFuel2Comp.Source, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Source", + "OtherFuel2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel2 CO2 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel2Comp.CO2Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CO2", + "OtherFuel2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel2 CO Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel2Comp.COPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CO", + "OtherFuel2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel2 CH4 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel2Comp.CH4Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "CH4", + "OtherFuel2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel2 NOx Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel2Comp.NOxPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NOx", + "OtherFuel2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel2 N2O Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel2Comp.N2OPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "N2O", + "OtherFuel2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel2 SO2 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel2Comp.SO2Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "SO2", + "OtherFuel2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel2 PM Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel2Comp.PMPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM", + "OtherFuel2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel2 PM10 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel2Comp.PM10Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM10", + "OtherFuel2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel2 PM2.5 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel2Comp.PM25Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "PM2.5", + "OtherFuel2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel2 NH3 Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel2Comp.NH3Pollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NH3", + "OtherFuel2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel2 NMVOC Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel2Comp.NMVOCPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "NMVOC", + "OtherFuel2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel2 Hg Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel2Comp.HgPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Hg", + "OtherFuel2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel2 Pb Emissions Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel2Comp.PbPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Pb", + "OtherFuel2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel2 Water Consumption Volume", + OutputProcessor::Unit::L, + Pollution.OtherFuel2Comp.WaterPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "WaterEnvironmentalFactors", + "OtherFuel2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel2 Nuclear High Level Waste Mass", + OutputProcessor::Unit::kg, + Pollution.OtherFuel2Comp.NucHiPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Nuclear High", + "OtherFuel2Emissions", + {}, + ""); + SetupOutputVariable(state, + "Environmental Impact OtherFuel2 Nuclear Low Level Waste Volume", + OutputProcessor::Unit::m3, + Pollution.OtherFuel2Comp.NucLoPollution, + OutputProcessor::SOVTimeStepType::System, + OutputProcessor::SOVStoreType::Summed, + "Site", + {}, + "Nuclear Low", + "OtherFuel2Emissions", + {}, + ""); + } break; } } // End of the NumEnergyTypes Do Loop From b4c272af9bede7d470513f9bdd01e65eda69395e Mon Sep 17 00:00:00 2001 From: Dareum Nam Date: Tue, 30 May 2023 15:23:02 -0600 Subject: [PATCH 03/26] change GetFuelFfactorInfo() str arg --- src/EnergyPlus/OutputReportTabular.cc | 26 +- src/EnergyPlus/PollutionModule.cc | 308 +++++++++--------- src/EnergyPlus/PollutionModule.hh | 10 +- .../unit/OutputReportTabular.unit.cc | 2 +- 4 files changed, 172 insertions(+), 174 deletions(-) diff --git a/src/EnergyPlus/OutputReportTabular.cc b/src/EnergyPlus/OutputReportTabular.cc index a40d0f8dbc2..6c70c8b2f69 100644 --- a/src/EnergyPlus/OutputReportTabular.cc +++ b/src/EnergyPlus/OutputReportTabular.cc @@ -2872,7 +2872,7 @@ void GetInputFuelAndPollutionFactors(EnergyPlusData &state) // + gatherTotalsBEPS(5)*sourceFactorSteam & !steam // ) / largeConversionFactor - GetFuelFactorInfo(state, "NaturalGas", fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); + GetFuelFactorInfo(state, Constant::eFuel::NaturalGas, fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); if (fuelFactorUsed) { ort->sourceFactorNaturalGas = curSourceFactor; ort->fuelfactorsused(2) = true; @@ -2885,7 +2885,7 @@ void GetInputFuelAndPollutionFactors(EnergyPlusData &state) ort->ffSchedIndex(2) = ffScheduleIndex; } - GetFuelFactorInfo(state, "FuelOilNo2", fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); + GetFuelFactorInfo(state, Constant::eFuel::FuelOilNo2, fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); if (fuelFactorUsed) { ort->sourceFactorFuelOil2 = curSourceFactor; ort->fuelfactorsused(7) = true; @@ -2898,7 +2898,7 @@ void GetInputFuelAndPollutionFactors(EnergyPlusData &state) ort->ffSchedIndex(11) = ffScheduleIndex; } - GetFuelFactorInfo(state, "FuelOilNo1", fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); + GetFuelFactorInfo(state, Constant::eFuel::FuelOilNo1, fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); if (fuelFactorUsed) { ort->sourceFactorFuelOil1 = curSourceFactor; ort->fuelfactorsused(6) = true; @@ -2911,7 +2911,7 @@ void GetInputFuelAndPollutionFactors(EnergyPlusData &state) ort->ffSchedIndex(10) = ffScheduleIndex; } - GetFuelFactorInfo(state, "Coal", fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); + GetFuelFactorInfo(state, Constant::eFuel::Coal, fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); if (fuelFactorUsed) { ort->sourceFactorCoal = curSourceFactor; ort->fuelfactorsused(5) = true; @@ -2924,7 +2924,7 @@ void GetInputFuelAndPollutionFactors(EnergyPlusData &state) ort->ffSchedIndex(9) = ffScheduleIndex; } - GetFuelFactorInfo(state, "Electricity", fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); + GetFuelFactorInfo(state, Constant::eFuel::Electricity, fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); if (fuelFactorUsed) { ort->sourceFactorElectric = curSourceFactor; ort->fuelfactorsused(1) = true; @@ -2937,7 +2937,7 @@ void GetInputFuelAndPollutionFactors(EnergyPlusData &state) ort->ffSchedIndex(1) = ffScheduleIndex; } - GetFuelFactorInfo(state, "Gasoline", fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); + GetFuelFactorInfo(state, Constant::eFuel::Gasoline, fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); if (fuelFactorUsed) { ort->sourceFactorGasoline = curSourceFactor; ort->fuelfactorsused(3) = true; @@ -2950,7 +2950,7 @@ void GetInputFuelAndPollutionFactors(EnergyPlusData &state) ort->ffSchedIndex(6) = ffScheduleIndex; } - GetFuelFactorInfo(state, "Propane", fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); + GetFuelFactorInfo(state, Constant::eFuel::Propane, fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); if (fuelFactorUsed) { ort->sourceFactorPropane = curSourceFactor; ort->fuelfactorsused(8) = true; @@ -2963,7 +2963,7 @@ void GetInputFuelAndPollutionFactors(EnergyPlusData &state) ort->ffSchedIndex(12) = ffScheduleIndex; } - GetFuelFactorInfo(state, "Diesel", fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); + GetFuelFactorInfo(state, Constant::eFuel::Diesel, fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); if (fuelFactorUsed) { ort->sourceFactorDiesel = curSourceFactor; ort->fuelfactorsused(4) = true; @@ -2976,7 +2976,7 @@ void GetInputFuelAndPollutionFactors(EnergyPlusData &state) ort->ffSchedIndex(8) = ffScheduleIndex; } - GetFuelFactorInfo(state, "DistrictCooling", fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); + GetFuelFactorInfo(state, Constant::eFuel::DistrictCooling, fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); if (fuelFactorUsed) { ort->ffUsed(3) = true; } @@ -2986,7 +2986,7 @@ void GetInputFuelAndPollutionFactors(EnergyPlusData &state) ort->ffSchedIndex(3) = ffScheduleIndex; } - GetFuelFactorInfo(state, "DistrictHeating", fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); + GetFuelFactorInfo(state, Constant::eFuel::DistrictHeating, fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); if (fuelFactorUsed) { ort->ffUsed(4) = true; } @@ -2996,7 +2996,7 @@ void GetInputFuelAndPollutionFactors(EnergyPlusData &state) ort->ffSchedIndex(4) = ffScheduleIndex; } - GetFuelFactorInfo(state, "Steam", fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); + GetFuelFactorInfo(state, Constant::eFuel::Steam, fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); if (fuelFactorUsed) { ort->ffUsed(5) = true; } @@ -3006,7 +3006,7 @@ void GetInputFuelAndPollutionFactors(EnergyPlusData &state) ort->ffSchedIndex(5) = ffScheduleIndex; } - GetFuelFactorInfo(state, "OtherFuel1", fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); + GetFuelFactorInfo(state, Constant::eFuel::OtherFuel1, fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); if (fuelFactorUsed) { ort->sourceFactorOtherFuel1 = curSourceFactor; ort->fuelfactorsused(11) = true; // should be source number @@ -3019,7 +3019,7 @@ void GetInputFuelAndPollutionFactors(EnergyPlusData &state) ort->ffSchedIndex(13) = ffScheduleIndex; } - GetFuelFactorInfo(state, "OtherFuel2", fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); + GetFuelFactorInfo(state, Constant::eFuel::OtherFuel2, fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); if (fuelFactorUsed) { ort->sourceFactorOtherFuel2 = curSourceFactor; ort->fuelfactorsused(12) = true; // should be source number diff --git a/src/EnergyPlus/PollutionModule.cc b/src/EnergyPlus/PollutionModule.cc index 1d8d4fe8944..1c2f2fa40f7 100644 --- a/src/EnergyPlus/PollutionModule.cc +++ b/src/EnergyPlus/PollutionModule.cc @@ -6285,11 +6285,11 @@ void ReadEnergyMeters(EnergyPlusData &state) // ***************************************************************************** void GetFuelFactorInfo(EnergyPlusData &state, - std::string const &fuelName, // input fuel name (standard from Tabular reports) - bool &fuelFactorUsed, // return value true if user has entered this fuel - Real64 &fuelSourceFactor, // if used, the source factor - bool &fuelFactorScheduleUsed, // if true, schedules for this fuel are used - int &ffScheduleIndex // if schedules for this fuel are used, return schedule index + Constant::eFuel const &fuelName, // input fuel name (standard from Tabular reports) + bool &fuelFactorUsed, // return value true if user has entered this fuel + Real64 &fuelSourceFactor, // if used, the source factor + bool &fuelFactorScheduleUsed, // if true, schedules for this fuel are used + int &ffScheduleIndex // if schedules for this fuel are used, return schedule index ) { @@ -6338,182 +6338,180 @@ void GetFuelFactorInfo(EnergyPlusData &state, fuelFactorScheduleUsed = false; ffScheduleIndex = 0; - { - auto const &SELECT_CASE_var(fuelName); - - if ((SELECT_CASE_var == "NaturalGas") || (SELECT_CASE_var == "Gas")) { - if (Pollution.NatGasCoef.FuelFactorUsed) { - fuelFactorUsed = true; - fuelSourceFactor = Pollution.NatGasCoef.Source; - if (Pollution.NatGasCoef.SourceSched == 0) { - fuelFactorScheduleUsed = false; - } else { - fuelFactorScheduleUsed = true; - ffScheduleIndex = Pollution.NatGasCoef.SourceSched; - } + switch (fuelName) { + case Constant::eFuel::NaturalGas: { + if (Pollution.NatGasCoef.FuelFactorUsed) { + fuelFactorUsed = true; + fuelSourceFactor = Pollution.NatGasCoef.Source; + if (Pollution.NatGasCoef.SourceSched == 0) { + fuelFactorScheduleUsed = false; } else { - fuelSourceFactor = 1.084; + fuelFactorScheduleUsed = true; + ffScheduleIndex = Pollution.NatGasCoef.SourceSched; } - - } else if (SELECT_CASE_var == "Electricity") { - if (Pollution.ElecCoef.FuelFactorUsed) { - fuelFactorUsed = true; - fuelSourceFactor = Pollution.ElecCoef.Source; - if (Pollution.ElecCoef.SourceSched == 0) { - fuelFactorScheduleUsed = false; - } else { - fuelFactorScheduleUsed = true; - ffScheduleIndex = Pollution.ElecCoef.SourceSched; - } + } else { + fuelSourceFactor = 1.084; + } + } break; + case Constant::eFuel::Electricity: { + if (Pollution.ElecCoef.FuelFactorUsed) { + fuelFactorUsed = true; + fuelSourceFactor = Pollution.ElecCoef.Source; + if (Pollution.ElecCoef.SourceSched == 0) { + fuelFactorScheduleUsed = false; } else { - fuelSourceFactor = 3.167; + fuelFactorScheduleUsed = true; + ffScheduleIndex = Pollution.ElecCoef.SourceSched; } - - } else if (SELECT_CASE_var == "FuelOilNo2") { - if (Pollution.FuelOil2Coef.FuelFactorUsed) { - fuelFactorUsed = true; - fuelSourceFactor = Pollution.FuelOil2Coef.Source; - if (Pollution.FuelOil2Coef.SourceSched == 0) { - fuelFactorScheduleUsed = false; - } else { - fuelFactorScheduleUsed = true; - ffScheduleIndex = Pollution.FuelOil2Coef.SourceSched; - } + } else { + fuelSourceFactor = 3.167; + } + } break; + case Constant::eFuel::FuelOilNo2: { + if (Pollution.FuelOil2Coef.FuelFactorUsed) { + fuelFactorUsed = true; + fuelSourceFactor = Pollution.FuelOil2Coef.Source; + if (Pollution.FuelOil2Coef.SourceSched == 0) { + fuelFactorScheduleUsed = false; } else { - fuelSourceFactor = 1.05; + fuelFactorScheduleUsed = true; + ffScheduleIndex = Pollution.FuelOil2Coef.SourceSched; } - - } else if (SELECT_CASE_var == "FuelOilNo1") { - if (Pollution.FuelOil1Coef.FuelFactorUsed) { - fuelFactorUsed = true; - fuelSourceFactor = Pollution.FuelOil1Coef.Source; - if (Pollution.FuelOil1Coef.SourceSched == 0) { - fuelFactorScheduleUsed = false; - } else { - fuelFactorScheduleUsed = true; - ffScheduleIndex = Pollution.FuelOil1Coef.SourceSched; - } + } else { + fuelSourceFactor = 1.05; + } + } break; + case Constant::eFuel::FuelOilNo1: { + if (Pollution.FuelOil1Coef.FuelFactorUsed) { + fuelFactorUsed = true; + fuelSourceFactor = Pollution.FuelOil1Coef.Source; + if (Pollution.FuelOil1Coef.SourceSched == 0) { + fuelFactorScheduleUsed = false; } else { - fuelSourceFactor = 1.05; + fuelFactorScheduleUsed = true; + ffScheduleIndex = Pollution.FuelOil1Coef.SourceSched; } - - } else if (SELECT_CASE_var == "Coal") { - if (Pollution.CoalCoef.FuelFactorUsed) { - fuelFactorUsed = true; - fuelSourceFactor = Pollution.CoalCoef.Source; - if (Pollution.CoalCoef.SourceSched == 0) { - fuelFactorScheduleUsed = false; - } else { - fuelFactorScheduleUsed = true; - ffScheduleIndex = Pollution.CoalCoef.SourceSched; - } + } else { + fuelSourceFactor = 1.05; + } + } break; + case Constant::eFuel::Coal: { + if (Pollution.CoalCoef.FuelFactorUsed) { + fuelFactorUsed = true; + fuelSourceFactor = Pollution.CoalCoef.Source; + if (Pollution.CoalCoef.SourceSched == 0) { + fuelFactorScheduleUsed = false; } else { - fuelSourceFactor = 1.05; + fuelFactorScheduleUsed = true; + ffScheduleIndex = Pollution.CoalCoef.SourceSched; } - - } else if (SELECT_CASE_var == "Gasoline") { - if (Pollution.GasolineCoef.FuelFactorUsed) { - fuelFactorUsed = true; - fuelSourceFactor = Pollution.GasolineCoef.Source; - if (Pollution.GasolineCoef.SourceSched == 0) { - fuelFactorScheduleUsed = false; - } else { - fuelFactorScheduleUsed = true; - ffScheduleIndex = Pollution.GasolineCoef.SourceSched; - } + } else { + fuelSourceFactor = 1.05; + } + } break; + case Constant::eFuel::Gasoline: { + if (Pollution.GasolineCoef.FuelFactorUsed) { + fuelFactorUsed = true; + fuelSourceFactor = Pollution.GasolineCoef.Source; + if (Pollution.GasolineCoef.SourceSched == 0) { + fuelFactorScheduleUsed = false; } else { - fuelSourceFactor = 1.05; + fuelFactorScheduleUsed = true; + ffScheduleIndex = Pollution.GasolineCoef.SourceSched; } - - } else if (SELECT_CASE_var == "Propane") { - if (Pollution.PropaneCoef.FuelFactorUsed) { - fuelFactorUsed = true; - fuelSourceFactor = Pollution.PropaneCoef.Source; - if (Pollution.PropaneCoef.SourceSched == 0) { - fuelFactorScheduleUsed = false; - } else { - fuelFactorScheduleUsed = true; - ffScheduleIndex = Pollution.PropaneCoef.SourceSched; - } + } else { + fuelSourceFactor = 1.05; + } + } break; + case Constant::eFuel::Propane: { + if (Pollution.PropaneCoef.FuelFactorUsed) { + fuelFactorUsed = true; + fuelSourceFactor = Pollution.PropaneCoef.Source; + if (Pollution.PropaneCoef.SourceSched == 0) { + fuelFactorScheduleUsed = false; } else { - fuelSourceFactor = 1.05; + fuelFactorScheduleUsed = true; + ffScheduleIndex = Pollution.PropaneCoef.SourceSched; } - - } else if (SELECT_CASE_var == "Diesel") { - if (Pollution.DieselCoef.FuelFactorUsed) { - fuelFactorUsed = true; - fuelSourceFactor = Pollution.DieselCoef.Source; - if (Pollution.DieselCoef.SourceSched == 0) { - fuelFactorScheduleUsed = false; - } else { - fuelFactorScheduleUsed = true; - ffScheduleIndex = Pollution.DieselCoef.SourceSched; - } + } else { + fuelSourceFactor = 1.05; + } + } break; + case Constant::eFuel::Diesel: { + if (Pollution.DieselCoef.FuelFactorUsed) { + fuelFactorUsed = true; + fuelSourceFactor = Pollution.DieselCoef.Source; + if (Pollution.DieselCoef.SourceSched == 0) { + fuelFactorScheduleUsed = false; } else { - fuelSourceFactor = 1.05; + fuelFactorScheduleUsed = true; + ffScheduleIndex = Pollution.DieselCoef.SourceSched; } - - } else if (SELECT_CASE_var == "OtherFuel1") { - if (Pollution.OtherFuel1Coef.FuelFactorUsed) { - fuelFactorUsed = true; - fuelSourceFactor = Pollution.OtherFuel1Coef.Source; - if (Pollution.OtherFuel1Coef.SourceSched == 0) { - fuelFactorScheduleUsed = false; - } else { - fuelFactorScheduleUsed = true; - ffScheduleIndex = Pollution.OtherFuel1Coef.SourceSched; - } + } else { + fuelSourceFactor = 1.05; + } + } break; + case Constant::eFuel::OtherFuel1: { + if (Pollution.OtherFuel1Coef.FuelFactorUsed) { + fuelFactorUsed = true; + fuelSourceFactor = Pollution.OtherFuel1Coef.Source; + if (Pollution.OtherFuel1Coef.SourceSched == 0) { + fuelFactorScheduleUsed = false; } else { - fuelSourceFactor = 1.0; + fuelFactorScheduleUsed = true; + ffScheduleIndex = Pollution.OtherFuel1Coef.SourceSched; } - - } else if (SELECT_CASE_var == "OtherFuel2") { - if (Pollution.OtherFuel2Coef.FuelFactorUsed) { - fuelFactorUsed = true; - fuelSourceFactor = Pollution.OtherFuel2Coef.Source; - if (Pollution.OtherFuel2Coef.SourceSched == 0) { - fuelFactorScheduleUsed = false; - } else { - fuelFactorScheduleUsed = true; - ffScheduleIndex = Pollution.OtherFuel2Coef.SourceSched; - } + } else { + fuelSourceFactor = 1.0; + } + } break; + case Constant::eFuel::OtherFuel2: { + if (Pollution.OtherFuel2Coef.FuelFactorUsed) { + fuelFactorUsed = true; + fuelSourceFactor = Pollution.OtherFuel2Coef.Source; + if (Pollution.OtherFuel2Coef.SourceSched == 0) { + fuelFactorScheduleUsed = false; } else { - fuelSourceFactor = 1.0; + fuelFactorScheduleUsed = true; + ffScheduleIndex = Pollution.OtherFuel2Coef.SourceSched; } - - } else if (SELECT_CASE_var == "DistrictHeating") { - if (Pollution.NatGasCoef.FuelFactorUsed) { - fuelFactorUsed = true; - fuelSourceFactor = Pollution.NatGasCoef.Source / Pollution.PurchHeatEffic; - if (Pollution.NatGasCoef.SourceSched == 0) { - fuelFactorScheduleUsed = false; - } else { - fuelFactorScheduleUsed = true; - ffScheduleIndex = Pollution.NatGasCoef.SourceSched; - } + } else { + fuelSourceFactor = 1.0; + } + } break; + case Constant::eFuel::DistrictHeating: { + if (Pollution.NatGasCoef.FuelFactorUsed) { + fuelFactorUsed = true; + fuelSourceFactor = Pollution.NatGasCoef.Source / Pollution.PurchHeatEffic; + if (Pollution.NatGasCoef.SourceSched == 0) { + fuelFactorScheduleUsed = false; } else { - fuelSourceFactor = 1.084 / Pollution.PurchHeatEffic; + fuelFactorScheduleUsed = true; + ffScheduleIndex = Pollution.NatGasCoef.SourceSched; } - - } else if (SELECT_CASE_var == "DistrictCooling") { - if (Pollution.ElecCoef.FuelFactorUsed) { - fuelFactorUsed = true; - fuelSourceFactor = Pollution.ElecCoef.Source / Pollution.PurchCoolCOP; - if (Pollution.ElecCoef.SourceSched == 0) { - fuelFactorScheduleUsed = false; - } else { - fuelFactorScheduleUsed = true; - ffScheduleIndex = Pollution.ElecCoef.SourceSched; - } + } else { + fuelSourceFactor = 1.084 / Pollution.PurchHeatEffic; + } + } break; + case Constant::eFuel::DistrictCooling: { + if (Pollution.ElecCoef.FuelFactorUsed) { + fuelFactorUsed = true; + fuelSourceFactor = Pollution.ElecCoef.Source / Pollution.PurchCoolCOP; + if (Pollution.ElecCoef.SourceSched == 0) { + fuelFactorScheduleUsed = false; } else { - fuelSourceFactor = 3.167 / Pollution.PurchCoolCOP; + fuelFactorScheduleUsed = true; + ffScheduleIndex = Pollution.ElecCoef.SourceSched; } - - } else if (SELECT_CASE_var == "Steam") { - fuelSourceFactor = 0.3 / Pollution.SteamConvEffic; - } else { + fuelSourceFactor = 3.167 / Pollution.PurchCoolCOP; } + } break; + case Constant::eFuel::Steam: { + fuelSourceFactor = 0.3 / Pollution.SteamConvEffic; + } break; + default: { + } break; } } diff --git a/src/EnergyPlus/PollutionModule.hh b/src/EnergyPlus/PollutionModule.hh index 742d09e7094..c2c727f079f 100644 --- a/src/EnergyPlus/PollutionModule.hh +++ b/src/EnergyPlus/PollutionModule.hh @@ -432,11 +432,11 @@ namespace PollutionModule { void ReadEnergyMeters(EnergyPlusData &state); void GetFuelFactorInfo(EnergyPlusData &state, - std::string const &fuelName, // input fuel name (standard from Tabular reports) - bool &fuelFactorUsed, // return value true if user has entered this fuel - Real64 &fuelSourceFactor, // if used, the source factor - bool &fuelFactorScheduleUsed, // if true, schedules for this fuel are used - int &ffScheduleIndex // if schedules for this fuel are used, return schedule index + Constant::eFuel const &fuelName, // input fuel name (standard from Tabular reports) + bool &fuelFactorUsed, // return value true if user has entered this fuel + Real64 &fuelSourceFactor, // if used, the source factor + bool &fuelFactorScheduleUsed, // if true, schedules for this fuel are used + int &ffScheduleIndex // if schedules for this fuel are used, return schedule index ); void GetEnvironmentalImpactFactorInfo(EnergyPlusData &state, diff --git a/tst/EnergyPlus/unit/OutputReportTabular.unit.cc b/tst/EnergyPlus/unit/OutputReportTabular.unit.cc index f507dc994c6..49442effa59 100644 --- a/tst/EnergyPlus/unit/OutputReportTabular.unit.cc +++ b/tst/EnergyPlus/unit/OutputReportTabular.unit.cc @@ -8517,7 +8517,7 @@ TEST_F(EnergyPlusFixture, OutputReportTabularTest_ConfirmConversionFactors) bool fFScheduleUsed; int ffScheduleIndex; - PollutionModule::GetFuelFactorInfo(*state, "Steam", fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); + PollutionModule::GetFuelFactorInfo(*state, Constant::eFuel::Steam, fuelFactorUsed, curSourceFactor, fFScheduleUsed, ffScheduleIndex); EXPECT_EQ(curSourceFactor, 1.2); } From 5d5900d8b7a86a9196ff6495d99769c797c0ba7b Mon Sep 17 00:00:00 2001 From: Dareum Nam Date: Fri, 2 Jun 2023 00:27:46 -0600 Subject: [PATCH 04/26] fix error --- src/EnergyPlus/PollutionModule.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/EnergyPlus/PollutionModule.cc b/src/EnergyPlus/PollutionModule.cc index 1c2f2fa40f7..f598a4b0fb8 100644 --- a/src/EnergyPlus/PollutionModule.cc +++ b/src/EnergyPlus/PollutionModule.cc @@ -4285,6 +4285,8 @@ void SetupPollutionMeterReporting(EnergyPlusData &state) {}, ""); } break; + default: + break; } } // End of the NumEnergyTypes Do Loop From 79ada403c6ec2e01b42ef79ac3d3ad6d4a1184bd Mon Sep 17 00:00:00 2001 From: Scott Horowitz Date: Mon, 26 Jun 2023 08:46:15 -0600 Subject: [PATCH 05/26] Fix low vs high curves in ResidentialACsAndHPsPerfCurves.idf --- datasets/ResidentialACsAndHPsPerfCurves.idf | 48 ++++++++++----------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/datasets/ResidentialACsAndHPsPerfCurves.idf b/datasets/ResidentialACsAndHPsPerfCurves.idf index 8685977b81e..003ea636b99 100644 --- a/datasets/ResidentialACsAndHPsPerfCurves.idf +++ b/datasets/ResidentialACsAndHPsPerfCurves.idf @@ -154,10 +154,10 @@ ! , !- Speed 1 Rated COP {W/W} ! , !- Speed 1 Rated Air Flow Rate {m3/s} ! , !- Rated Evaporator Fan Power Per Volume Flow Rate {W/(m3/s)} -! ACHighStageCoolingCAPFTemp, !- Speed 1 Total Cooling Capacity Function of Temperature Curve Name -! ACHighStageCoolingCAPFFF, !- Speed 1 Total Cooling Capacity Function of Flow Fraction Curve Name -! ACHighStageCoolingEIRFTemp, !- Speed 1 Energy Input Ratio Function of Temperature Curve Name -! ACHighStageCoolingEIRFFF, !- Speed 1 Energy Input Ratio Function of Flow Fraction Curve Name +! ACLowStageCoolingCAPFTemp, !- Speed 1 Total Cooling Capacity Function of Temperature Curve Name +! ACLowStageCoolingCAPFFF, !- Speed 1 Total Cooling Capacity Function of Flow Fraction Curve Name +! ACLowStageCoolingEIRFTemp, !- Speed 1 Energy Input Ratio Function of Temperature Curve Name +! ACLowStageCoolingEIRFFF, !- Speed 1 Energy Input Ratio Function of Flow Fraction Curve Name ! AC2StageCoolingPLFFPLR, !- Speed 1 Part Load Fraction Correlation Curve Name ! , !- Speed 1 Nominal Time for Condensate Removal to Begin {s} ! , !- Speed 1 Ratio of Initial Moisture Evaporation Rate and Steady State Latent Capacity {dimensionless} @@ -173,10 +173,10 @@ ! , !- Speed 2 Rated COP {W/W} ! , !- Speed 2 Rated Air Flow Rate {m3/s} ! , !- Rated Evaporator Fan Power Per Volume Flow Rate {W/(m3/s)} -! ACLowStageCoolingCAPFTemp, !- Speed 2 Total Cooling Capacity Function of Temperature Curve Name -! ACLowStageCoolingCAPFFF, !- Speed 2 Total Cooling Capacity Function of Flow Fraction Curve Name -! ACLowStageCoolingEIRFTemp, !- Speed 2 Energy Input Ratio Function of Temperature Curve Name -! ACLowStageCoolingEIRFFF, !- Speed 2 Energy Input Ratio Function of Flow Fraction Curve Name +! ACHighStageCoolingCAPFTemp, !- Speed 2 Total Cooling Capacity Function of Temperature Curve Name +! ACHighStageCoolingCAPFFF, !- Speed 2 Total Cooling Capacity Function of Flow Fraction Curve Name +! ACHighStageCoolingEIRFTemp, !- Speed 2 Energy Input Ratio Function of Temperature Curve Name +! ACHighStageCoolingEIRFFF, !- Speed 2 Energy Input Ratio Function of Flow Fraction Curve Name ! AC2StageCoolingPLFFPLR, !- Speed 2 Part Load Fraction Correlation Curve Name ! , !- Speed 2 Nominal Time for Condensate Removal to Begin {s} ! , !- Speed 2 Ratio of Initial Moisture Evaporation Rate and steady state Latent Capacity {dimensionless} @@ -570,10 +570,10 @@ ! , !- Speed 1 Rated COP {W/W} ! , !- Speed 1 Rated Air Flow Rate {m3/s} ! , !- Rated Evaporator Fan Power Per Volume Flow Rate {W/(m3/s)} -! HPHighStageCoolingCAPFTemp, !- Speed 1 Total Cooling Capacity Function of Temperature Curve Name -! HPHighStageCoolingCAPFFF, !- Speed 1 Total Cooling Capacity Function of Flow Fraction Curve Name -! HPHighStageCoolingEIRFTemp, !- Speed 1 Energy Input Ratio Function of Temperature Curve Name -! HPHighStageCoolingEIRFFF, !- Speed 1 Energy Input Ratio Function of Flow Fraction Curve Name +! HPLowStageCoolingCAPFTemp, !- Speed 1 Total Cooling Capacity Function of Temperature Curve Name +! HPLowStageCoolingCAPFFF, !- Speed 1 Total Cooling Capacity Function of Flow Fraction Curve Name +! HPLowStageCoolingEIRFTemp, !- Speed 1 Energy Input Ratio Function of Temperature Curve Name +! HPLowStageCoolingEIRFFF, !- Speed 1 Energy Input Ratio Function of Flow Fraction Curve Name ! HP2StageCoolingPLFFPLR, !- Speed 1 Part Load Fraction Correlation Curve Name ! , !- Speed 1 Nominal Time for Condensate Removal to Begin {s} ! , !- Speed 1 Ratio of Initial Moisture Evaporation Rate and Steady State Latent Capacity {dimensionless} @@ -589,10 +589,10 @@ ! , !- Speed 2 Rated COP {W/W} ! , !- Speed 2 Rated Air Flow Rate {m3/s} ! , !- Rated Evaporator Fan Power Per Volume Flow Rate {W/(m3/s)} -! HPLowStageCoolingCAPFTemp, !- Speed 2 Total Cooling Capacity Function of Temperature Curve Name -! HPLowStageCoolingCAPFFF, !- Speed 2 Total Cooling Capacity Function of Flow Fraction Curve Name -! HPLowStageCoolingEIRFTemp, !- Speed 2 Energy Input Ratio Function of Temperature Curve Name -! HPLowStageCoolingEIRFFF, !- Speed 2 Energy Input Ratio Function of Flow Fraction Curve Name +! HPHighStageCoolingCAPFTemp, !- Speed 2 Total Cooling Capacity Function of Temperature Curve Name +! HPHighStageCoolingCAPFFF, !- Speed 2 Total Cooling Capacity Function of Flow Fraction Curve Name +! HPHighStageCoolingEIRFTemp, !- Speed 2 Energy Input Ratio Function of Temperature Curve Name +! HPHighStageCoolingEIRFFF, !- Speed 2 Energy Input Ratio Function of Flow Fraction Curve Name ! HP2StageCoolingPLFFPLR, !- Speed 2 Part Load Fraction Correlation Curve Name ! , !- Speed 2 Nominal Time for Condensate Removal to Begin {s} ! , !- Speed 2 Ratio of Initial Moisture Evaporation Rate and steady state Latent Capacity {dimensionless} @@ -762,10 +762,10 @@ ! , !- Speed 1 Rated COP {W/W} ! , !- Speed 1 Rated Air Flow Rate {m3/s} ! , !- Speed 1 Rated Supply Air Fan Power Per Volume Flow Rate {W/(m3/s)} -! HPHighStageHeatingCAPFTemp, !- Speed 1 Total Heating Capacity Function of Temperature Curve Name -! HPHighStageHeatingCAPFFF, !- Speed 1 Total Heating Capacity Function of Flow Fraction Curve Name -! HPHighStageHeatingEIRFTemp, !- Speed 1 Energy Input Ratio Function of Temperature Curve Name -! HPHighStageHeatingEIRFFF, !- Speed 1 Energy Input Ratio Function of Flow Fraction Curve Name +! HPLowStageHeatingCAPFTemp, !- Speed 1 Total Heating Capacity Function of Temperature Curve Name +! HPLowStageHeatingCAPFFF, !- Speed 1 Total Heating Capacity Function of Flow Fraction Curve Name +! HPLowStageHeatingEIRFTemp, !- Speed 1 Energy Input Ratio Function of Temperature Curve Name +! HPLowStageHeatingEIRFFF, !- Speed 1 Energy Input Ratio Function of Flow Fraction Curve Name ! HP2StageHeatingPLFFPLR, !- Speed 1 Part Load Fraction Correlation Curve Name ! , !- Speed 1 Rated Waste Heat Fraction of Power Input {dimensionless} ! , !- Speed 1 Waste Heat Function of Temperature Curve Name @@ -773,10 +773,10 @@ ! , !- Speed 2 Rated COP {W/W} ! , !- Speed 2 Rated Air Flow Rate {m3/s} ! , !- Speed 2 Rated Supply Air Fan Power Per Volume Flow Rate {W/(m3/s)} -! HPLowStageHeatingCAPFTemp, !- Speed 2 Total Heating Capacity Function of Temperature Curve Name -! HPLowStageHeatingCAPFFF, !- Speed 2 Total Heating Capacity Function of Flow Fraction Curve Name -! HPLowStageHeatingEIRFTemp, !- Speed 2 Energy Input Ratio Function of Temperature Curve Name -! HPLowStageHeatingEIRFFF, !- Speed 2 Energy Input Ratio Function of Flow Fraction Curve Name +! HPHighStageHeatingCAPFTemp, !- Speed 2 Total Heating Capacity Function of Temperature Curve Name +! HPHighStageHeatingCAPFFF, !- Speed 2 Total Heating Capacity Function of Flow Fraction Curve Name +! HPHighStageHeatingEIRFTemp, !- Speed 2 Energy Input Ratio Function of Temperature Curve Name +! HPHighStageHeatingEIRFFF, !- Speed 2 Energy Input Ratio Function of Flow Fraction Curve Name ! HP2StageHeatingPLFFPLR, !- Speed 2 Part Load Fraction Correlation Curve Name ! , !- Speed 2 Rated Waste Heat Fraction of Power Input {dimensionless} ! ; !- Speed 2 Waste Heat Function of Temperature Curve Name From a8a41edae3009f71ad02499cec44b91d0c9de6fb Mon Sep 17 00:00:00 2001 From: Dareum Nam Date: Tue, 18 Jul 2023 13:01:57 -0600 Subject: [PATCH 06/26] fix failed test --- src/EnergyPlus/PollutionModule.cc | 4 ++-- tst/EnergyPlus/unit/PollutionModule.unit.cc | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/EnergyPlus/PollutionModule.cc b/src/EnergyPlus/PollutionModule.cc index f598a4b0fb8..aa2d8b65696 100644 --- a/src/EnergyPlus/PollutionModule.cc +++ b/src/EnergyPlus/PollutionModule.cc @@ -276,8 +276,8 @@ void GetPollutionFactorInput(EnergyPlusData &state) state.dataIPShortCut->cAlphaFieldNames, state.dataIPShortCut->cNumericFieldNames); - FuelType.FuelTypeNames(Loop) = static_cast( - getEnumerationValue(Constant::eFuelNamesUC, UtilityRoutines::MakeUPPERCase(state.dataIPShortCut->cAlphaArgs(1)))); + FuelType.FuelTypeNames(Loop) = + static_cast(getEnumValue(Constant::eFuelNamesUC, UtilityRoutines::makeUPPER(state.dataIPShortCut->cAlphaArgs(1)))); switch (FuelType.FuelTypeNames(Loop)) { case Constant::eFuel::NaturalGas: { diff --git a/tst/EnergyPlus/unit/PollutionModule.unit.cc b/tst/EnergyPlus/unit/PollutionModule.unit.cc index a3c23716cc7..52816b39140 100644 --- a/tst/EnergyPlus/unit/PollutionModule.unit.cc +++ b/tst/EnergyPlus/unit/PollutionModule.unit.cc @@ -469,6 +469,7 @@ TEST_F(EnergyPlusFixture, PollutionModule_TestOutputVariables) ASSERT_TRUE(process_idf(idf_objects)); state->dataPollutionModule->FuelType.FuelTypeNames.allocate(10); + state->dataPollutionModule->FuelType.FuelTypeNames = Constant::eFuel::Invalid; state->dataPollutionModule->GetInputFlagPollution = true; PollutionModule::SetupPollutionMeterReporting(*state); From 0f8a39d0670baf1ac2555423ebcfeb85d14b7cf4 Mon Sep 17 00:00:00 2001 From: Dareum Nam Date: Wed, 19 Jul 2023 09:51:14 -0600 Subject: [PATCH 07/26] fix failed tests --- src/EnergyPlus/PollutionModule.hh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/EnergyPlus/PollutionModule.hh b/src/EnergyPlus/PollutionModule.hh index c2c727f079f..0cc471e1c4d 100644 --- a/src/EnergyPlus/PollutionModule.hh +++ b/src/EnergyPlus/PollutionModule.hh @@ -395,15 +395,15 @@ namespace PollutionModule { // Default Constructor FuelTypeProps() - : FuelTypeNames({1, static_cast(PollFactor::Num)}), Elec(0.0), NatGas(0.0), FuelOil1(0.0), FuelOil2(0.0), Coal(0.0), Gasoline(0.0), - Propane(0.0), Diesel(0.0), OtherFuel1(0.0), OtherFuel2(0.0), ElecPurch(0.0), ElecSold(0.0), ElecFacilityIndex(0), - DieselFacilityIndex(0), PurchCoolFacilityIndex(0), PurchHeatFacilityIndex(0), NatGasFacilityIndex(0), GasolineFacilityIndex(0), - CoalFacilityIndex(0), FuelOil1FacilityIndex(0), FuelOil2FacilityIndex(0), PropaneFacilityIndex(0), OtherFuel1FacilityIndex(0), - OtherFuel2FacilityIndex(0), ElecProducedFacilityIndex(0), SteamFacilityIndex(0), ElecPurchasedFacilityIndex(0), - ElecSurplusSoldFacilityIndex(0), ElecFacility(0.0), DieselFacility(0.0), PurchCoolFacility(0.0), PurchHeatFacility(0.0), - NatGasFacility(0.0), GasolineFacility(0.0), CoalFacility(0.0), FuelOil1Facility(0.0), FuelOil2Facility(0.0), PropaneFacility(0.0), - OtherFuel1Facility(0.0), OtherFuel2Facility(0.0), ElecProducedFacility(0.0), SteamFacility(0.0), ElecPurchasedFacility(0.0), - ElecSurplusSoldFacility(0.0) + : FuelTypeNames({1, static_cast(PollFactor::Num)}, Constant::eFuel::Invalid), Elec(0.0), NatGas(0.0), FuelOil1(0.0), FuelOil2(0.0), + Coal(0.0), Gasoline(0.0), Propane(0.0), Diesel(0.0), OtherFuel1(0.0), OtherFuel2(0.0), ElecPurch(0.0), ElecSold(0.0), + ElecFacilityIndex(0), DieselFacilityIndex(0), PurchCoolFacilityIndex(0), PurchHeatFacilityIndex(0), NatGasFacilityIndex(0), + GasolineFacilityIndex(0), CoalFacilityIndex(0), FuelOil1FacilityIndex(0), FuelOil2FacilityIndex(0), PropaneFacilityIndex(0), + OtherFuel1FacilityIndex(0), OtherFuel2FacilityIndex(0), ElecProducedFacilityIndex(0), SteamFacilityIndex(0), + ElecPurchasedFacilityIndex(0), ElecSurplusSoldFacilityIndex(0), ElecFacility(0.0), DieselFacility(0.0), PurchCoolFacility(0.0), + PurchHeatFacility(0.0), NatGasFacility(0.0), GasolineFacility(0.0), CoalFacility(0.0), FuelOil1Facility(0.0), FuelOil2Facility(0.0), + PropaneFacility(0.0), OtherFuel1Facility(0.0), OtherFuel2Facility(0.0), ElecProducedFacility(0.0), SteamFacility(0.0), + ElecPurchasedFacility(0.0), ElecSurplusSoldFacility(0.0) { } }; From d791c8732e38eb4cb6581316572bbcae9e504730 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Wed, 19 Jul 2023 16:01:02 +0200 Subject: [PATCH 08/26] Add some testing for the CLI: both CMake + gtest --- src/EnergyPlus/CMakeLists.txt | 38 ++ tst/EnergyPlus/unit/CMakeLists.txt | 15 +- .../unit/CommandLineInterface.unit.cc | 410 ++++++++++++++++++ 3 files changed, 459 insertions(+), 4 deletions(-) create mode 100644 tst/EnergyPlus/unit/CommandLineInterface.unit.cc diff --git a/src/EnergyPlus/CMakeLists.txt b/src/EnergyPlus/CMakeLists.txt index 37f61443507..587c9e5f20d 100644 --- a/src/EnergyPlus/CMakeLists.txt +++ b/src/EnergyPlus/CMakeLists.txt @@ -1070,6 +1070,44 @@ if(BUILD_TESTING) set_tests_properties("API.test_SysExit" PROPERTIES ENVIRONMENT PYTHONPATH=${DIR_WITH_PY_ENERGYPLUS}) add_test(NAME "API.test_OutputFiles" COMMAND "${Python_EXECUTABLE}" "${PROJECT_SOURCE_DIR}/tst/EnergyPlus/api/test_OutputFiles.py") set_tests_properties("API.test_OutputFiles" PROPERTIES ENVIRONMENT PYTHONPATH=${DIR_WITH_PY_ENERGYPLUS}) + + set(CLI_TEST_DIR "${PROJECT_BINARY_DIR}/tst/cli") + set(EXAMPLES_FILES_DIR "${PROJECT_SOURCE_DIR}/testfiles") + + set(NON_ASCII_DIRNAME "térmicà") + set(INPUT_TEST_DIR "${CLI_TEST_DIR}/${NON_ASCII_DIRNAME}") + file(MAKE_DIRECTORY ${INPUT_TEST_DIR}) + + set(TEST_CASE "1ZoneUncontrolled") + set(IDF_FILE "${EXAMPLES_FILES_DIR}/${TEST_CASE}.idf") + configure_file(${IDF_FILE} "${INPUT_TEST_DIR}/${TEST_CASE}.idf" COPYONLY) + + add_test(NAME energyplus.TestNonASCIIDirsAndFiles.NoPlugin.FromWithin + COMMAND energyplus -D -d "${CLI_TEST_DIR}/NoPlugin.FromWithin/out-${NON_ASCII_DIRNAME}" ${TEST_CASE}.idf + WORKING_DIRECTORY "${CLI_TEST_DIR}/${NON_ASCII_DIRNAME}" + ) + + add_test(NAME energyplus.TestNonASCIIDirsAndFiles.NoPlugin.FromOutside + COMMAND energyplus -D -d "${CLI_TEST_DIR}/NoPlugin.FromOutside/out-${NON_ASCII_DIRNAME}" ${NON_ASCII_DIRNAME}/${TEST_CASE}.idf + WORKING_DIRECTORY "${CLI_TEST_DIR}" + ) + + set(TEST_CASE "PythonPlugin1ZoneUncontrolledCondFD") + set(IDF_FILE "${EXAMPLES_FILES_DIR}/${TEST_CASE}.idf") + configure_file(${IDF_FILE} "${INPUT_TEST_DIR}/${TEST_CASE}.idf" COPYONLY) + set(PY_FILE "${EXAMPLES_FILES_DIR}/${TEST_CASE}.py") + configure_file(${PY_FILE} "${INPUT_TEST_DIR}/${TEST_CASE}.py" COPYONLY) + + add_test(NAME energyplus.TestNonASCIIDirsAndFiles.PythonPlugin.FromWithin + COMMAND energyplus -D -d "${CLI_TEST_DIR}/PythonPlugin.FromWithin/out-${NON_ASCII_DIRNAME}" ${TEST_CASE}.idf + WORKING_DIRECTORY "${CLI_TEST_DIR}/${NON_ASCII_DIRNAME}" + ) + + add_test(NAME energyplus.TestNonASCIIDirsAndFiles.PythonPlugin.FromOutside + COMMAND energyplus -D -d "${CLI_TEST_DIR}/PythonPlugin.FromOutside/out-${NON_ASCII_DIRNAME}" ${NON_ASCII_DIRNAME}/${TEST_CASE}.idf + WORKING_DIRECTORY "${CLI_TEST_DIR}" + ) + endif() if(UNIX AND NOT APPLE) diff --git a/tst/EnergyPlus/unit/CMakeLists.txt b/tst/EnergyPlus/unit/CMakeLists.txt index f291923a758..798ee0ae05e 100644 --- a/tst/EnergyPlus/unit/CMakeLists.txt +++ b/tst/EnergyPlus/unit/CMakeLists.txt @@ -274,13 +274,20 @@ if(LINK_WITH_PYTHON) endif() endif() -if(CMAKE_HOST_UNIX) - if(NOT APPLE) - list(APPEND test_dependencies dl) - endif() +if(CMAKE_HOST_UNIX AND NOT APPLE) + list(APPEND test_dependencies dl) endif() # Executable name will be EnergyPlus_tests # Execute energyplus_tests --help for options using gtest runner # Execute energyplus_tests with no arguments to run all tests create_test_targets(energyplus "${test_src}" "${test_dependencies}" True) + + +set(test_src + Fixtures/EnergyPlusFixture.cc + Fixtures/EnergyPlusFixture.hh + CommandLineInterface.unit.cc + main.cc +) +create_test_targets(energyplusapi "${test_src}" "${test_dependencies}" True) diff --git a/tst/EnergyPlus/unit/CommandLineInterface.unit.cc b/tst/EnergyPlus/unit/CommandLineInterface.unit.cc new file mode 100644 index 00000000000..738375abf5c --- /dev/null +++ b/tst/EnergyPlus/unit/CommandLineInterface.unit.cc @@ -0,0 +1,410 @@ +// EnergyPlus, Copyright (c) 1996-2023, The Board of Trustees of the University of Illinois, +// The Regents of the University of California, through Lawrence Berkeley National Laboratory +// (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge +// National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other +// contributors. All rights reserved. +// +// NOTICE: This Software was developed under funding from the U.S. Department of Energy and the +// U.S. Government consequently retains certain rights. As such, the U.S. Government has been +// granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable, +// worldwide license in the Software to reproduce, distribute copies to the public, prepare +// derivative works, and perform publicly and display publicly, and to permit others to do so. +// +// Redistribution and use in source and binary forms, with or without modification, are permitted +// provided that the following conditions are met: +// +// (1) Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// (2) Redistributions in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory, +// the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific prior +// written permission. +// +// (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form +// without changes from the version obtained under this License, or (ii) Licensee makes a +// reference solely to the software portion of its product, Licensee must refer to the +// software as "EnergyPlus version X" software, where "X" is the version number Licensee +// obtained under this License and may not use a different name for the software. Except as +// specifically required in this Section (4), Licensee shall not use in a company name, a +// product name, in advertising, publicity, or other promotional activities any name, trade +// name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly +// similar designation, without the U.S. Department of Energy's prior written consent. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// Google Test Headers +#include + +// EnergyPlus Headers +#include +#include +#include +#include + +#include "Fixtures/EnergyPlusFixture.hh" + +#include + +#include +#include +#include +#include +#include + +using namespace EnergyPlus; +using namespace EnergyPlus::CommandLineInterface; + +namespace EnergyPlus { + +// Helper to construct an `int argc, const char *argv[]`. Take size() - 1 for argc +std::vector stringVecToArgcArgv(const std::vector &input) +{ + std::vector result; + + // remember the nullptr terminator + result.reserve(input.size() + 2); + result.push_back("energyplus"); + + std::transform(std::begin(input), std::end(input), std::back_inserter(result), [](const std::string &s) { return s.data(); }); + result.push_back(nullptr); + return result; +} + +struct ExpectedParams +{ + bool AnnualSimulation = false; + bool DDOnlySimulation = false; + fs::path outDirPath; + fs::path inputIddFilePath = "Energy+.idd"; + + bool runExpandObjects = false; + bool runEPMacro = false; + + bool runReadVars = false; + bool outputEpJSONConversion = false; + bool outputEpJSONConversionOnly = false; + + int numThread = 1; + fs::path inputWeatherFilePath = "in.epw"; + fs::path inputFilePath = "in.idf"; + + std::string prefixOutName = "eplus"; + std::string suffixType = "L"; + + std::string VerStringVar; +}; + +class CommandLineInterfaceFixture : public EnergyPlusFixture +{ +protected: + void SetUp() override + { + EnergyPlusFixture::SetUp(); + state->dataGlobal->eplusRunningViaAPI = true; // Avoid using `exit()` + + expectedParams.inputFilePath = configured_source_directory() / "tst/EnergyPlus/unit/Resources/UnitaryHybridUnitTest_DOSA.idf"; + expectedParams.inputIddFilePath = + FileSystem::getParentDirectoryPath(FileSystem::getAbsolutePath(FileSystem::getProgramPath())) / "Energy+.idd"; + + // This is done in EnergyPlusPgm, which we bypass + state->dataStrGlobals->CurrentDateTime = " unknown date/time"; + state->dataStrGlobals->VerStringVar = EnergyPlus::DataStringGlobals::VerString + "," + state->dataStrGlobals->CurrentDateTime; + expectedParams.VerStringVar = state->dataStrGlobals->VerStringVar; + } + +public: + ExpectedParams expectedParams; + + int processArgsHelper(const std::vector &input) + { + auto result = stringVecToArgcArgv(input); + return ProcessArgs(*state, result.size() - 1, result.data()); + } + + template ::value || !std::is_pointer::value>::type * = nullptr> + static bool + CompareX(const char *lhs_expression, const char *rhs_expression, const T1 &lhs, const T2 &rhs, std::stringstream &ss, const char *file, int line) + { + const auto assertion_result = ::testing::internal::EqHelper::Compare(lhs_expression, rhs_expression, lhs, rhs); + if (!assertion_result) { + ss << '\n' << assertion_result.message() << '\n' << file << ":" << line; + return false; + } + return true; + } + +#define FORMAT_EXPECT_EQ(v1, v2, ss) CompareX(#v1, #v2, v1, v2, (ss), __FILE__, __LINE__) + + ::testing::AssertionResult testExpected(const ExpectedParams &expectedParams) + { + std::stringstream ss; + bool result = true; + + result &= FORMAT_EXPECT_EQ(expectedParams.AnnualSimulation, state->dataGlobal->AnnualSimulation, ss); + result &= FORMAT_EXPECT_EQ(expectedParams.DDOnlySimulation, state->dataGlobal->DDOnlySimulation, ss); + result &= FORMAT_EXPECT_EQ(expectedParams.outDirPath, state->dataStrGlobals->outDirPath, ss); + result &= FORMAT_EXPECT_EQ(expectedParams.inputIddFilePath, state->dataStrGlobals->inputIddFilePath, ss); + + // Can't capture runExpandObjects not runEPMacro + result &= FORMAT_EXPECT_EQ(expectedParams.runReadVars, state->dataGlobal->runReadVars, ss); + result &= FORMAT_EXPECT_EQ(expectedParams.outputEpJSONConversion, state->dataGlobal->outputEpJSONConversion, ss); + result &= FORMAT_EXPECT_EQ(expectedParams.outputEpJSONConversionOnly, state->dataGlobal->outputEpJSONConversionOnly, ss); + + result &= FORMAT_EXPECT_EQ(expectedParams.numThread, state->dataGlobal->numThread, ss); + result &= FORMAT_EXPECT_EQ(expectedParams.inputWeatherFilePath, state->files.inputWeatherFilePath.filePath, ss); + result &= FORMAT_EXPECT_EQ(expectedParams.inputFilePath, state->dataStrGlobals->inputFilePath, ss); + + std::string tableSuffix; + if (expectedParams.suffixType == "L") { + tableSuffix = "tbl"; + } else if (expectedParams.suffixType == "D") { + tableSuffix = "-table"; + } else if (expectedParams.suffixType == "C") { + tableSuffix = "Table"; + } + fs::path const outputTblHtmFilePath = expectedParams.outDirPath / fmt::format("{}{}.htm", expectedParams.prefixOutName, tableSuffix); + result &= FORMAT_EXPECT_EQ(outputTblHtmFilePath, state->dataStrGlobals->outputTblHtmFilePath, ss); + if (!result) { + return ::testing::AssertionFailure() << ss.str(); + } + return ::testing::AssertionSuccess(); + } + +#if 0 + void testExpected(const ExpectedParams &expectedParams) + { + EXPECT_EQ(expectedParams.AnnualSimulation, state->dataGlobal->AnnualSimulation); + EXPECT_EQ(expectedParams.DDOnlySimulation, state->dataGlobal->DDOnlySimulation); + + EXPECT_EQ(expectedParams.outDirPath, state->dataStrGlobals->outDirPath); + EXPECT_EQ(expectedParams.inputIddFilePath, state->dataStrGlobals->inputIddFilePath); + + // Can't capture runExpandObjects not runEPMacro + + EXPECT_EQ(expectedParams.outputEpJSONConversion, state->dataGlobal->outputEpJSONConversion); + EXPECT_EQ(expectedParams.outputEpJSONConversionOnly, state->dataGlobal->outputEpJSONConversionOnly); + + EXPECT_EQ(expectedParams.numThread, state->dataGlobal->numThread); + + EXPECT_EQ(expectedParams.inputWeatherFilePath, state->files.inputWeatherFilePath.filePath); + EXPECT_EQ(expectedParams.inputFilePath, state->dataStrGlobals->inputFilePath); + + std::string tableSuffix; + if (expectedParams.suffixType == "L") { + tableSuffix = "tbl"; + } else if (expectedParams.suffixType == "D") { + tableSuffix = "-table"; + } else if (expectedParams.suffixType == "L") { + tableSuffix = "Table"; + } + fs::path const outputTblHtmFilePath = expectedParams.outDirPath / fmt::format("{}{}.htm", expectedParams.prefixOutName, tableSuffix); + + EXPECT_EQ(outputTblHtmFilePath, state->dataStrGlobals->outputTblHtmFilePath); + } +#endif +}; +} // namespace EnergyPlus + +TEST_F(CommandLineInterfaceFixture, IdfOnly) +{ + const int exitcode = processArgsHelper({expectedParams.inputFilePath.generic_string()}); + EXPECT_EQ(static_cast(ReturnCodes::Success), exitcode); + compare_cout_stream(""); + EXPECT_TRUE(testExpected(expectedParams)); +} + +TEST_F(CommandLineInterfaceFixture, IdfDoesNotExist) +{ + expectedParams.inputFilePath = FileSystem::getAbsolutePath("WRONG.IDF"); + const int exitcode = processArgsHelper({expectedParams.inputFilePath.generic_string()}); + EXPECT_EQ(static_cast(ReturnCodes::Failure), exitcode); + compare_cout_stream(delimited_string({ + fmt::format("ERROR: Could not find input data file: {}.", expectedParams.inputFilePath.string()), + "Type 'energyplus --help' for usage.", + })); + EXPECT_TRUE(testExpected(expectedParams)); +} + +TEST_F(CommandLineInterfaceFixture, AnnualSimulation) +{ + expectedParams.AnnualSimulation = true; + for (const std::string &flag : {"-a", "--annual"}) { + SCOPED_TRACE("Flag: '" + flag + "'"); + const int exitcode = processArgsHelper({flag, expectedParams.inputFilePath.generic_string()}); + EXPECT_EQ(static_cast(ReturnCodes::Success), exitcode); + compare_cout_stream(""); + EXPECT_TRUE(testExpected(expectedParams)); + } +} + +TEST_F(CommandLineInterfaceFixture, DDSimulation) +{ + expectedParams.DDOnlySimulation = true; + for (const std::string &flag : {"-D", "--design-day"}) { + SCOPED_TRACE("Flag: '" + flag + "'"); + const int exitcode = processArgsHelper({flag, expectedParams.inputFilePath.generic_string()}); + EXPECT_EQ(static_cast(ReturnCodes::Success), exitcode); + compare_cout_stream(""); + EXPECT_TRUE(testExpected(expectedParams)); + } +} + +TEST_F(CommandLineInterfaceFixture, AnnualExcludesDDSimulation) +{ + const int exitcode = processArgsHelper({"-D", "-a", expectedParams.inputFilePath.generic_string()}); + EXPECT_EQ(static_cast(ReturnCodes::Failure), exitcode); + compare_cout_stream(delimited_string({ + "ERROR: Cannot force both design-day and annual simulations. Set either '-D' or '-a', but not both.", + "Type 'energyplus --help' for usage.", + })); +} + +TEST_F(CommandLineInterfaceFixture, WeatherFileExists) +{ + expectedParams.inputWeatherFilePath = configured_source_directory() / "weather/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.epw"; + const int exitcode = + processArgsHelper({"-w", expectedParams.inputWeatherFilePath.generic_string(), expectedParams.inputFilePath.generic_string()}); + EXPECT_EQ(static_cast(ReturnCodes::Success), exitcode); + compare_cout_stream(""); + EXPECT_TRUE(testExpected(expectedParams)); +} + +TEST_F(CommandLineInterfaceFixture, WeatherFileDoesNotExists) +{ + expectedParams.inputWeatherFilePath = "WRONG.epw"; + for (const std::string &flag : {"-w", "--weather"}) { + SCOPED_TRACE("Flag: '" + flag + "'"); + const int exitcode = + processArgsHelper({flag, expectedParams.inputWeatherFilePath.generic_string(), expectedParams.inputFilePath.generic_string()}); + EXPECT_EQ(static_cast(ReturnCodes::Failure), exitcode); + compare_cout_stream(delimited_string({ + "ERROR: Could not find weather file: " + FileSystem::getAbsolutePath(expectedParams.inputWeatherFilePath).generic_string() + ".", + "Type 'energyplus --help' for usage.", + })); + EXPECT_TRUE(testExpected(expectedParams)); + } +} + +TEST_F(CommandLineInterfaceFixture, Version) +{ + for (const std::string &flag : {"-v", "--version"}) { + SCOPED_TRACE("Flag: '" + flag + "'"); + const int exitcode = processArgsHelper({flag}); + EXPECT_EQ(static_cast(ReturnCodes::SuccessButHelper), exitcode); + compare_cout_stream(delimited_string({expectedParams.VerStringVar})); + } +} + +TEST_F(CommandLineInterfaceFixture, Convert) +{ + expectedParams.outputEpJSONConversion = true; + for (const std::string &flag : {"-c", "--convert"}) { + SCOPED_TRACE("Flag: '" + flag + "'"); + const int exitcode = processArgsHelper({flag, expectedParams.inputFilePath.generic_string()}); + EXPECT_EQ(static_cast(ReturnCodes::Success), exitcode); + compare_cout_stream(""); + EXPECT_TRUE(testExpected(expectedParams)); + } +} + +TEST_F(CommandLineInterfaceFixture, ConvertOnly) +{ + expectedParams.outputEpJSONConversionOnly = true; + const int exitcode = processArgsHelper({"--convert-only", expectedParams.inputFilePath.generic_string()}); + EXPECT_EQ(static_cast(ReturnCodes::Success), exitcode); + compare_cout_stream(""); + EXPECT_TRUE(testExpected(expectedParams)); +} + +TEST_F(CommandLineInterfaceFixture, runReadVars) +{ + expectedParams.runReadVars = true; + for (const std::string &flag : {"-r", "--readvars"}) { + SCOPED_TRACE("Flag: '" + flag + "'"); + const int exitcode = processArgsHelper({flag, expectedParams.inputFilePath.generic_string()}); + EXPECT_EQ(static_cast(ReturnCodes::Success), exitcode); + compare_cout_stream(""); + EXPECT_TRUE(testExpected(expectedParams)); + } +} + +TEST_F(CommandLineInterfaceFixture, numThread) +{ + struct TestCase + { + int j; + int expectedCorrectedJ; + std::string errorMessage; + }; + + const int Nproc = static_cast(std::thread::hardware_concurrency()); + + const std::array test_data{{ + {4, 4, ""}, + {0, 1, "Invalid value for -j arg. Defaulting to 1."}, + {100, Nproc, fmt::format("Invalid value for -j arg. Value exceeds num available. Defaulting to num available. -j {}", Nproc)}, + }}; + + for (auto [j, expectedCorrectedJ, error_message] : test_data) { + SCOPED_TRACE(fmt::format("Passing j={}", j)); + expectedParams.numThread = expectedCorrectedJ; + for (const std::string &flag : {"-j", "--jobs"}) { + SCOPED_TRACE("Flag: '" + flag + "'"); + const int exitcode = processArgsHelper({flag, std::to_string(j), expectedParams.inputFilePath.generic_string()}); + EXPECT_EQ(static_cast(ReturnCodes::Success), exitcode); + if (error_message.empty()) { + EXPECT_FALSE(has_cout_output()); + } else { + compare_cout_stream(delimited_string({error_message})); + } + EXPECT_TRUE(testExpected(expectedParams)); + } + } +} + +TEST_F(CommandLineInterfaceFixture, SuffixPrefix) +{ + { + SCOPED_TRACE("Short Version"); + expectedParams.suffixType = "D"; + expectedParams.prefixOutName = "prefix"; + + const int exitcode = + processArgsHelper({"-s", expectedParams.suffixType, "-p", expectedParams.prefixOutName, expectedParams.inputFilePath.generic_string()}); + EXPECT_EQ(static_cast(ReturnCodes::Success), exitcode); + compare_cout_stream(""); + EXPECT_TRUE(testExpected(expectedParams)); + } + + { + SCOPED_TRACE("Long Version"); + expectedParams.suffixType = "C"; + expectedParams.prefixOutName = "other"; + + const int exitcode = processArgsHelper({"--output-suffix", + expectedParams.suffixType, + "--output-prefix", + expectedParams.prefixOutName, + expectedParams.inputFilePath.generic_string()}); + EXPECT_EQ(static_cast(ReturnCodes::Success), exitcode); + compare_cout_stream(""); + EXPECT_TRUE(testExpected(expectedParams)); + } +} From 9b97c017cd606dcc6748dbd14911d936f901d6a7 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Wed, 19 Jul 2023 17:14:46 +0200 Subject: [PATCH 09/26] Tweak slightly to also catch the Legacy mode and check cerr_stream --- .../unit/CommandLineInterface.unit.cc | 56 ++++++++++++++++++- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/tst/EnergyPlus/unit/CommandLineInterface.unit.cc b/tst/EnergyPlus/unit/CommandLineInterface.unit.cc index 738375abf5c..47657739c59 100644 --- a/tst/EnergyPlus/unit/CommandLineInterface.unit.cc +++ b/tst/EnergyPlus/unit/CommandLineInterface.unit.cc @@ -59,9 +59,11 @@ #include #include +#include #include #include #include +#include #include using namespace EnergyPlus; @@ -110,12 +112,23 @@ struct ExpectedParams class CommandLineInterfaceFixture : public EnergyPlusFixture { protected: + static void SetUpTestCase() + { + EnergyPlusFixture::SetUpTestCase(); + + // For the "legacy" mode, we need in.idf / in.epw in the current directory + auto inputFilePath = configured_source_directory() / "tst/EnergyPlus/unit/Resources/UnitaryHybridUnitTest_DOSA.idf"; + fs::copy_file(inputFilePath, FileSystem::getAbsolutePath("in.idf"), fs::copy_options::skip_existing); + + auto inputWeatherFilePath = configured_source_directory() / "weather/USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.epw"; + fs::copy_file(inputWeatherFilePath, FileSystem::getAbsolutePath("in.epw"), fs::copy_options::skip_existing); + } + void SetUp() override { EnergyPlusFixture::SetUp(); state->dataGlobal->eplusRunningViaAPI = true; // Avoid using `exit()` - expectedParams.inputFilePath = configured_source_directory() / "tst/EnergyPlus/unit/Resources/UnitaryHybridUnitTest_DOSA.idf"; expectedParams.inputIddFilePath = FileSystem::getParentDirectoryPath(FileSystem::getAbsolutePath(FileSystem::getProgramPath())) / "Energy+.idd"; @@ -222,11 +235,34 @@ class CommandLineInterfaceFixture : public EnergyPlusFixture }; } // namespace EnergyPlus +TEST_F(CommandLineInterfaceFixture, Legacy) +{ + expectedParams.inputIddFilePath = "Energy+.idd"; + const int exitcode = processArgsHelper({}); + EXPECT_EQ(static_cast(ReturnCodes::Success), exitcode); + compare_cout_stream(""); + compare_cerr_stream(""); + EXPECT_TRUE(testExpected(expectedParams)); +} + TEST_F(CommandLineInterfaceFixture, IdfOnly) { + expectedParams.inputFilePath = configured_source_directory() / "tst/EnergyPlus/unit/Resources/UnitaryHybridUnitTest_DOSA.idf"; const int exitcode = processArgsHelper({expectedParams.inputFilePath.generic_string()}); EXPECT_EQ(static_cast(ReturnCodes::Success), exitcode); compare_cout_stream(""); + compare_cerr_stream(""); + EXPECT_TRUE(testExpected(expectedParams)); +} + +TEST_F(CommandLineInterfaceFixture, IdfOnly_NativePath) +{ + expectedParams.inputFilePath = + FileSystem::makeNativePath(configured_source_directory() / "tst/EnergyPlus/unit/Resources/UnitaryHybridUnitTest_DOSA.idf"); + const int exitcode = processArgsHelper({expectedParams.inputFilePath.string()}); + EXPECT_EQ(static_cast(ReturnCodes::Success), exitcode); + compare_cout_stream(""); + compare_cerr_stream(""); EXPECT_TRUE(testExpected(expectedParams)); } @@ -236,9 +272,10 @@ TEST_F(CommandLineInterfaceFixture, IdfDoesNotExist) const int exitcode = processArgsHelper({expectedParams.inputFilePath.generic_string()}); EXPECT_EQ(static_cast(ReturnCodes::Failure), exitcode); compare_cout_stream(delimited_string({ - fmt::format("ERROR: Could not find input data file: {}.", expectedParams.inputFilePath.string()), + fmt::format("ERROR: Could not find input data file: {}.", FileSystem::makeNativePath(expectedParams.inputFilePath).string()), "Type 'energyplus --help' for usage.", })); + compare_cerr_stream(""); EXPECT_TRUE(testExpected(expectedParams)); } @@ -250,6 +287,7 @@ TEST_F(CommandLineInterfaceFixture, AnnualSimulation) const int exitcode = processArgsHelper({flag, expectedParams.inputFilePath.generic_string()}); EXPECT_EQ(static_cast(ReturnCodes::Success), exitcode); compare_cout_stream(""); + compare_cerr_stream(""); EXPECT_TRUE(testExpected(expectedParams)); } } @@ -262,6 +300,7 @@ TEST_F(CommandLineInterfaceFixture, DDSimulation) const int exitcode = processArgsHelper({flag, expectedParams.inputFilePath.generic_string()}); EXPECT_EQ(static_cast(ReturnCodes::Success), exitcode); compare_cout_stream(""); + compare_cerr_stream(""); EXPECT_TRUE(testExpected(expectedParams)); } } @@ -274,6 +313,7 @@ TEST_F(CommandLineInterfaceFixture, AnnualExcludesDDSimulation) "ERROR: Cannot force both design-day and annual simulations. Set either '-D' or '-a', but not both.", "Type 'energyplus --help' for usage.", })); + compare_cerr_stream(""); } TEST_F(CommandLineInterfaceFixture, WeatherFileExists) @@ -283,6 +323,7 @@ TEST_F(CommandLineInterfaceFixture, WeatherFileExists) processArgsHelper({"-w", expectedParams.inputWeatherFilePath.generic_string(), expectedParams.inputFilePath.generic_string()}); EXPECT_EQ(static_cast(ReturnCodes::Success), exitcode); compare_cout_stream(""); + compare_cerr_stream(""); EXPECT_TRUE(testExpected(expectedParams)); } @@ -295,9 +336,11 @@ TEST_F(CommandLineInterfaceFixture, WeatherFileDoesNotExists) processArgsHelper({flag, expectedParams.inputWeatherFilePath.generic_string(), expectedParams.inputFilePath.generic_string()}); EXPECT_EQ(static_cast(ReturnCodes::Failure), exitcode); compare_cout_stream(delimited_string({ - "ERROR: Could not find weather file: " + FileSystem::getAbsolutePath(expectedParams.inputWeatherFilePath).generic_string() + ".", + "ERROR: Could not find weather file: " + + FileSystem::getAbsolutePath(FileSystem::makeNativePath(expectedParams.inputWeatherFilePath)).string() + ".", "Type 'energyplus --help' for usage.", })); + compare_cerr_stream(""); EXPECT_TRUE(testExpected(expectedParams)); } } @@ -309,6 +352,7 @@ TEST_F(CommandLineInterfaceFixture, Version) const int exitcode = processArgsHelper({flag}); EXPECT_EQ(static_cast(ReturnCodes::SuccessButHelper), exitcode); compare_cout_stream(delimited_string({expectedParams.VerStringVar})); + compare_cerr_stream(""); } } @@ -320,6 +364,7 @@ TEST_F(CommandLineInterfaceFixture, Convert) const int exitcode = processArgsHelper({flag, expectedParams.inputFilePath.generic_string()}); EXPECT_EQ(static_cast(ReturnCodes::Success), exitcode); compare_cout_stream(""); + compare_cerr_stream(""); EXPECT_TRUE(testExpected(expectedParams)); } } @@ -330,6 +375,7 @@ TEST_F(CommandLineInterfaceFixture, ConvertOnly) const int exitcode = processArgsHelper({"--convert-only", expectedParams.inputFilePath.generic_string()}); EXPECT_EQ(static_cast(ReturnCodes::Success), exitcode); compare_cout_stream(""); + compare_cerr_stream(""); EXPECT_TRUE(testExpected(expectedParams)); } @@ -341,6 +387,7 @@ TEST_F(CommandLineInterfaceFixture, runReadVars) const int exitcode = processArgsHelper({flag, expectedParams.inputFilePath.generic_string()}); EXPECT_EQ(static_cast(ReturnCodes::Success), exitcode); compare_cout_stream(""); + compare_cerr_stream(""); EXPECT_TRUE(testExpected(expectedParams)); } } @@ -374,6 +421,7 @@ TEST_F(CommandLineInterfaceFixture, numThread) } else { compare_cout_stream(delimited_string({error_message})); } + compare_cerr_stream(""); EXPECT_TRUE(testExpected(expectedParams)); } } @@ -390,6 +438,7 @@ TEST_F(CommandLineInterfaceFixture, SuffixPrefix) processArgsHelper({"-s", expectedParams.suffixType, "-p", expectedParams.prefixOutName, expectedParams.inputFilePath.generic_string()}); EXPECT_EQ(static_cast(ReturnCodes::Success), exitcode); compare_cout_stream(""); + compare_cerr_stream(""); EXPECT_TRUE(testExpected(expectedParams)); } @@ -405,6 +454,7 @@ TEST_F(CommandLineInterfaceFixture, SuffixPrefix) expectedParams.inputFilePath.generic_string()}); EXPECT_EQ(static_cast(ReturnCodes::Success), exitcode); compare_cout_stream(""); + compare_cerr_stream(""); EXPECT_TRUE(testExpected(expectedParams)); } } From 004549d582f7b2ebe58abed45cb9ccc7a12f0f42 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Fri, 7 Jul 2023 09:04:36 +0200 Subject: [PATCH 10/26] WIP windows --- cmake/CompilerFlags.cmake | 1 + src/EnergyPlus/CMakeLists.txt | 2 +- src/EnergyPlus/CommandLineInterface.cc | 55 ++++++------ src/EnergyPlus/CommandLineInterface.hh | 3 +- src/EnergyPlus/CommandLineStringUtilities.hh | 93 ++++++++++++++++++++ src/EnergyPlus/StringUtilities.hh | 2 +- src/EnergyPlus/api/EnergyPlusPgm.cc | 19 ++-- src/EnergyPlus/api/EnergyPlusPgm.hh | 5 +- src/EnergyPlus/api/runtime.cc | 3 +- src/EnergyPlus/main.cc | 39 +++++++- 10 files changed, 179 insertions(+), 43 deletions(-) create mode 100644 src/EnergyPlus/CommandLineStringUtilities.hh diff --git a/cmake/CompilerFlags.cmake b/cmake/CompilerFlags.cmake index 2701766a082..5d68c71c716 100644 --- a/cmake/CompilerFlags.cmake +++ b/cmake/CompilerFlags.cmake @@ -24,6 +24,7 @@ if(MSVC AND NOT ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")) # Visual C++ (VS target_compile_options(project_options INTERFACE /EHsc) target_compile_options(project_options INTERFACE /MP) # Enables multi-processor compilation of source within a single project target_compile_options(project_options INTERFACE /Zc:externConstexpr) # allows constexpr to be extern'd in headers, which is part of the standard, and supported by default on non-vs compilers + target_compile_options(project_options INTERFACE /utf-8) # Specifies both the source character set and the execution character set as UTF-8 # string(REGEX REPLACE "/W3" "/W1" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" # )# Increase to /W2 then /W3 as more serious warnings are addressed (using regex to avoid VC override warnings) diff --git a/src/EnergyPlus/CMakeLists.txt b/src/EnergyPlus/CMakeLists.txt index 587c9e5f20d..b1ebb073f19 100644 --- a/src/EnergyPlus/CMakeLists.txt +++ b/src/EnergyPlus/CMakeLists.txt @@ -834,7 +834,7 @@ if(APPLE OR UNIX) else() # windows add_executable(energyplus main.cc "${CMAKE_CURRENT_BINARY_DIR}/energyplus.rc") endif() -target_link_libraries(energyplus PRIVATE energyplusapi project_options project_fp_options project_warnings) +target_link_libraries(energyplus PRIVATE fmt::fmt energyplusapi project_options project_fp_options project_warnings) set_target_properties(energyplus PROPERTIES VERSION ${ENERGYPLUS_VERSION}) set_target_properties(energyplusapi PROPERTIES VERSION ${ENERGYPLUS_VERSION}) diff --git a/src/EnergyPlus/CommandLineInterface.cc b/src/EnergyPlus/CommandLineInterface.cc index cdcca5514f9..4d110b8df70 100644 --- a/src/EnergyPlus/CommandLineInterface.cc +++ b/src/EnergyPlus/CommandLineInterface.cc @@ -61,13 +61,15 @@ #include #include +#include + namespace EnergyPlus { namespace CommandLineInterface { using namespace ez; - int ProcessArgs(EnergyPlusData &state, int argc, const char *argv[]) + int ProcessArgs(EnergyPlusData &state, const std::vector &args) { typedef std::string::size_type size_type; @@ -75,11 +77,10 @@ namespace CommandLineInterface { // and expand multiple short options into separate arguments std::vector arguments; - for (int i = 0; i < argc; ++i) { + std::string const dash("-"); - std::string inputArg(argv[i]); + for (const auto &inputArg : args) { - std::string const dash("-"); size_type const doubleDashPosition = inputArg.find("--"); size_type const equalsPosition = inputArg.find("="); @@ -95,23 +96,6 @@ namespace CommandLineInterface { } } - // Fix This is problematic for a few reasons: - // Using ezOptionParser with a raw C-string interface is asking for trouble: Find something taking std::string if possible - // Passing out pointers returned by c_str() is bad form: - // They are pointers to internally-managed memory in std::string - // They are invalid as soon as the string goes out of scope or is modified - // In this case the strings may be in scope and unmodified until parse is done but this is red flag usage - // convert to vector of C strings for option parser - std::vector cStrArgs; - cStrArgs.reserve(arguments.size()); - for (size_type i = 0; i < arguments.size(); ++i) { - cStrArgs.push_back(arguments[i].c_str()); - } - - size_type const argCount = cStrArgs.size(); - - bool const legacyMode = (argCount == 1); - // Define options ezOptionParser opt; @@ -160,10 +144,27 @@ namespace CommandLineInterface { opt.example = "energyplus -w weather.epw -r input.idf"; - std::string errorFollowUp = "Type 'energyplus --help' for usage."; + const std::string errorFollowUp = "Type 'energyplus --help' for usage."; + + // Fix This is problematic for a few reasons: + // Using ezOptionParser with a raw C-string interface is asking for trouble: Find something taking std::string if possible + // Passing out pointers returned by c_str() is bad form: + // They are pointers to internally-managed memory in std::string + // They are invalid as soon as the string goes out of scope or is modified + // In this case the strings may be in scope and unmodified until parse is done but this is red flag usage + // convert to vector of C strings for option parser + std::vector cStrArgs; + cStrArgs.reserve(arguments.size()); + for (const auto &argument : arguments) { + cStrArgs.push_back(argument.c_str()); + } + + size_type const argCount = arguments.size(); + + bool const legacyMode = (argCount == 1); // Parse arguments - opt.parse(argCount, &cStrArgs[0]); + opt.parse(static_cast(argCount), cStrArgs.data()); // print arguments parsed (useful for debugging) // std::string pretty; @@ -183,14 +184,14 @@ namespace CommandLineInterface { { std::string inputWeatherFileName; opt.get("-w")->getString(inputWeatherFileName); - state.files.inputWeatherFilePath.filePath = fs::path{inputWeatherFileName}; + state.files.inputWeatherFilePath.filePath = CLI::to_path(inputWeatherFileName); } { // TODO: should this be in IOFiles as an InputFile? std::string inputIddFileName; opt.get("-i")->getString(inputIddFileName); - state.dataStrGlobals->inputIddFilePath = fs::path{inputIddFileName}; + state.dataStrGlobals->inputIddFilePath = CLI::to_path(inputIddFileName); } if (!opt.isSet("-i") && !legacyMode) { @@ -200,7 +201,7 @@ namespace CommandLineInterface { { std::string outDirPathName; opt.get("-d")->getString(outDirPathName); - state.dataStrGlobals->outDirPath = fs::path{outDirPathName}; + state.dataStrGlobals->outDirPath = CLI::to_path(outDirPathName); } state.dataGlobal->runReadVars = opt.isSet("-r"); @@ -249,7 +250,7 @@ namespace CommandLineInterface { } if (opt.lastArgs.size() == 1) { - state.dataStrGlobals->inputFilePath = fs::path{*opt.lastArgs[0]}; + state.dataStrGlobals->inputFilePath = CLI::to_path(*opt.lastArgs[0]); } else if (opt.lastArgs.empty()) { state.dataStrGlobals->inputFilePath = "in.idf"; } diff --git a/src/EnergyPlus/CommandLineInterface.hh b/src/EnergyPlus/CommandLineInterface.hh index bb1f712716f..f2c9cf397cd 100644 --- a/src/EnergyPlus/CommandLineInterface.hh +++ b/src/EnergyPlus/CommandLineInterface.hh @@ -50,6 +50,7 @@ // C++ Headers #include +#include // EnergyPlus Headers #include @@ -72,7 +73,7 @@ namespace CommandLineInterface { }; // Process command line arguments - int ENERGYPLUSLIB_API ProcessArgs(EnergyPlusData &state, int argc, const char *argv[]); + int ENERGYPLUSLIB_API ProcessArgs(EnergyPlusData &state, const std::vector &args); void ReadINIFile(InputFile &inputFile, // Unit number of the opened INI file std::string const &Heading, // Heading for the parameters ('[heading]') diff --git a/src/EnergyPlus/CommandLineStringUtilities.hh b/src/EnergyPlus/CommandLineStringUtilities.hh new file mode 100644 index 00000000000..c82ac227dcf --- /dev/null +++ b/src/EnergyPlus/CommandLineStringUtilities.hh @@ -0,0 +1,93 @@ +// The Regents of the University of California, through Lawrence Berkeley National Laboratory +// (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge +// National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other +// contributors. All rights reserved. +// +// NOTICE: This Software was developed under funding from the U.S. Department of Energy and the +// U.S. Government consequently retains certain rights. As such, the U.S. Government has been +// granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable, +// worldwide license in the Software to reproduce, distribute copies to the public, prepare +// derivative works, and perform publicly and display publicly, and to permit others to do so. +// +// Redistribution and use in source and binary forms, with or without modification, are permitted +// provided that the following conditions are met: +// +// (1) Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// (2) Redistributions in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory, +// the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific prior +// written permission. +// +// (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form +// without changes from the version obtained under this License, or (ii) Licensee makes a +// reference solely to the software portion of its product, Licensee must refer to the +// software as "EnergyPlus version X" software, where "X" is the version number Licensee +// obtained under this License and may not use a different name for the software. Except as +// specifically required in this Section (4), Licensee shall not use in a company name, a +// product name, in advertising, publicity, or other promotional activities any name, trade +// name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly +// similar designation, without the U.S. Department of Energy's prior written consent. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#include +#include +#include +#include + +namespace CLI { +namespace detail { + inline std::string narrow_impl(const wchar_t *str, std::size_t str_size) + { +#ifdef _WIN32 + return std::wstring_convert>().to_bytes(str, str + str_size); +#else + return std::wstring_convert>().to_bytes(str, str + str_size); +#endif + } +} // namespace detail + +inline std::string narrow(const wchar_t *str) +{ + return detail::narrow_impl(str, std::wcslen(str)); +} + +inline std::string narrow(const std::wstring &str) +{ + return detail::narrow_impl(str.data(), str.size()); +} + +inline std::wstring widen(const std::string &str) +{ +#ifdef _WIN32 + return std::wstring_convert>().from_bytes(str.data(), str.data() + str.size()); +#else + return std::wstring_convert>().from_bytes(str.data(), str.data() + str.size()); +#endif // _WIN32 +} + +inline std::filesystem::path to_path(const std::string &str) +{ + return { +#ifdef _WIN32 + widen(str) +#else + str +#endif // _WIN32 + }; +} +} // namespace CLI diff --git a/src/EnergyPlus/StringUtilities.hh b/src/EnergyPlus/StringUtilities.hh index 2748eb14369..3f12c78a384 100644 --- a/src/EnergyPlus/StringUtilities.hh +++ b/src/EnergyPlus/StringUtilities.hh @@ -157,7 +157,7 @@ inline auto nth_occurrence(std::string_view input_str, char const search_char, s return pos; } -template bool readList(std::string_view input, Param &&... param) +template bool readList(std::string_view input, Param &&...param) { if constexpr (std::conjunction_v...> || std::conjunction_v...>) { size_t index = 0; diff --git a/src/EnergyPlus/api/EnergyPlusPgm.cc b/src/EnergyPlus/api/EnergyPlusPgm.cc index e7a21016a11..ef0565f6577 100644 --- a/src/EnergyPlus/api/EnergyPlusPgm.cc +++ b/src/EnergyPlus/api/EnergyPlusPgm.cc @@ -179,6 +179,9 @@ // C++ Headers #include #include +#include +#include + #ifndef NDEBUG #ifdef __unix__ #include @@ -219,7 +222,7 @@ #include #endif -int EnergyPlusPgm(int argc, const char *argv[], std::string const &filepath) +int EnergyPlusPgm(const std::vector &args, std::string const &filepath) { EnergyPlus::EnergyPlusData state; //// these need to be set early to be used in help and version output messaging @@ -233,7 +236,7 @@ int EnergyPlusPgm(int argc, const char *argv[], std::string const &filepath) } state.dataStrGlobals->VerStringVar = EnergyPlus::DataStringGlobals::VerString + "," + state.dataStrGlobals->CurrentDateTime; - EnergyPlus::CommandLineInterface::ProcessArgs(state, argc, argv); + EnergyPlus::CommandLineInterface::ProcessArgs(state, args); return RunEnergyPlus(state, filepath); } @@ -333,9 +336,7 @@ int initializeEnergyPlus(EnergyPlus::EnergyPlusData &state, std::string const &f return EXIT_FAILURE; } state.dataStrGlobals->ProgramPath = filepath + DataStringGlobals::pathChar; - int dummy_argc = 1; - const char *dummy_argv[1] = {"energyplus"}; - CommandLineInterface::ProcessArgs(state, dummy_argc, dummy_argv); + CommandLineInterface::ProcessArgs(state, {"energyplus"}); } return commonRun(state); @@ -418,7 +419,7 @@ int RunEnergyPlus(EnergyPlus::EnergyPlusData &state, std::string const &filepath return wrapUpEnergyPlus(state); } -int runEnergyPlusAsLibrary(EnergyPlus::EnergyPlusData &state, int argc, const char *argv[]) +int runEnergyPlusAsLibrary(EnergyPlus::EnergyPlusData &state, const std::vector &args) { // PROGRAM INFORMATION: // AUTHOR Linda K. Lawrie, et al @@ -441,7 +442,7 @@ int runEnergyPlusAsLibrary(EnergyPlus::EnergyPlusData &state, int argc, const ch if (!std::cerr.good()) std::cerr.clear(); if (!std::cout.good()) std::cout.clear(); - int return_code = EnergyPlus::CommandLineInterface::ProcessArgs(state, argc, argv); + int return_code = EnergyPlus::CommandLineInterface::ProcessArgs(state, args); if (return_code == static_cast(EnergyPlus::CommandLineInterface::ReturnCodes::Failure)) { return return_code; } else if (return_code == static_cast(EnergyPlus::CommandLineInterface::ReturnCodes::SuccessButHelper)) { @@ -450,7 +451,9 @@ int runEnergyPlusAsLibrary(EnergyPlus::EnergyPlusData &state, int argc, const ch } int status = initializeAsLibrary(state); - if (status || state.dataGlobal->outputEpJSONConversionOnly) return status; + if (status || state.dataGlobal->outputEpJSONConversionOnly) { + return status; + } try { EnergyPlus::SimulationManager::ManageSimulation(state); } catch (const EnergyPlus::FatalError &e) { diff --git a/src/EnergyPlus/api/EnergyPlusPgm.hh b/src/EnergyPlus/api/EnergyPlusPgm.hh index dfb80ad1f07..ac32eb1e125 100644 --- a/src/EnergyPlus/api/EnergyPlusPgm.hh +++ b/src/EnergyPlus/api/EnergyPlusPgm.hh @@ -52,6 +52,7 @@ // C++ Headers #include +#include namespace EnergyPlus { struct EnergyPlusData; @@ -65,11 +66,11 @@ int initializeEnergyPlus(EnergyPlus::EnergyPlusData &state, std::string const &f int wrapUpEnergyPlus(EnergyPlus::EnergyPlusData &state); -int ENERGYPLUSLIB_API EnergyPlusPgm(int argc, const char *argv[], std::string const &filepath = std::string()); +int ENERGYPLUSLIB_API EnergyPlusPgm(const std::vector &args, std::string const &filepath = std::string()); int ENERGYPLUSLIB_API RunEnergyPlus(EnergyPlus::EnergyPlusData &state, std::string const &filepath = std::string()); -int runEnergyPlusAsLibrary(EnergyPlus::EnergyPlusData &state, int argc, const char *argv[]); +int runEnergyPlusAsLibrary(EnergyPlus::EnergyPlusData &state, const std::vector &args); void ENERGYPLUSLIB_API StoreProgressCallback(EnergyPlus::EnergyPlusData &state, void (*f)(int const)); diff --git a/src/EnergyPlus/api/runtime.cc b/src/EnergyPlus/api/runtime.cc index 2428aa43819..e164ac96533 100644 --- a/src/EnergyPlus/api/runtime.cc +++ b/src/EnergyPlus/api/runtime.cc @@ -72,7 +72,8 @@ int energyplus(EnergyPlusState state, int argc, const char *argv[]) return 1; } thisState->ready = false; - return runEnergyPlusAsLibrary(*thisState, argc, argv); + std::vector args(argv, std::next(argv, static_cast(argc))); + return runEnergyPlusAsLibrary(*thisState, args); } void stopSimulation(EnergyPlusState state) diff --git a/src/EnergyPlus/main.cc b/src/EnergyPlus/main.cc index bcedae0d44c..dbd6fffc93a 100644 --- a/src/EnergyPlus/main.cc +++ b/src/EnergyPlus/main.cc @@ -45,8 +45,41 @@ // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. +// EnergyPlus Headers #include +// C++ Headers +#include +#include +#include +#include + +#include +#include + +#ifdef _WIN32 +// EnergyPlus Headers +#include +#include + +int wmain(int argc, wchar_t *wargv[]) +{ + for (int i = 0; i < argc; ++i) { + fmt::print(L"wargv[{}] = {}\n", i, wargv[i]); + } + std::vector wargs(wargv, std::next(wargv, static_cast(argc))); + std::vector args; + args.reserve(wargs.size()); + std::transform(wargs.cbegin(), wargs.cend(), std::back_inserter(args), [](const std::wstring &ws) { return CLI::narrow(ws); }); + for (const auto &wstr : wargs) { + fmt::print(L"wargs={}\n", wstr); + } + fmt::print("args={}\n", args); + + return EnergyPlusPgm(args); +} +#else + #ifdef DEBUG_ARITHM_GCC_OR_CLANG #include #endif @@ -56,6 +89,8 @@ int main(int argc, const char *argv[]) #ifdef DEBUG_ARITHM_GCC_OR_CLANG feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW); #endif - - return EnergyPlusPgm(argc, argv); + std::vector args(argv, std::next(argv, static_cast(argc))); + fmt::print("args={}\n", args); + return EnergyPlusPgm(std::move(args)); } +#endif From dec88b2bd1c84bb9cd1bb1d03fc449809b867ea5 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Wed, 19 Jul 2023 16:13:16 +0200 Subject: [PATCH 11/26] Modify test now that ProcessArgs takes a std::vector already. --- .../unit/CommandLineInterface.unit.cc | 20 +++---------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/tst/EnergyPlus/unit/CommandLineInterface.unit.cc b/tst/EnergyPlus/unit/CommandLineInterface.unit.cc index 47657739c59..5ab30529916 100644 --- a/tst/EnergyPlus/unit/CommandLineInterface.unit.cc +++ b/tst/EnergyPlus/unit/CommandLineInterface.unit.cc @@ -71,20 +71,6 @@ using namespace EnergyPlus::CommandLineInterface; namespace EnergyPlus { -// Helper to construct an `int argc, const char *argv[]`. Take size() - 1 for argc -std::vector stringVecToArgcArgv(const std::vector &input) -{ - std::vector result; - - // remember the nullptr terminator - result.reserve(input.size() + 2); - result.push_back("energyplus"); - - std::transform(std::begin(input), std::end(input), std::back_inserter(result), [](const std::string &s) { return s.data(); }); - result.push_back(nullptr); - return result; -} - struct ExpectedParams { bool AnnualSimulation = false; @@ -141,10 +127,10 @@ class CommandLineInterfaceFixture : public EnergyPlusFixture public: ExpectedParams expectedParams; - int processArgsHelper(const std::vector &input) + int processArgsHelper(std::vector input) { - auto result = stringVecToArgcArgv(input); - return ProcessArgs(*state, result.size() - 1, result.data()); + input.insert(input.begin(), "energyplus"); + return ProcessArgs(*state, input); } template Date: Fri, 7 Jul 2023 10:38:24 +0200 Subject: [PATCH 12/26] Replace deprecated (C++17) codecvt with other facilities --- src/EnergyPlus/CommandLineStringUtilities.hh | 108 +++++++++++++++---- src/EnergyPlus/main.cc | 5 +- 2 files changed, 90 insertions(+), 23 deletions(-) diff --git a/src/EnergyPlus/CommandLineStringUtilities.hh b/src/EnergyPlus/CommandLineStringUtilities.hh index c82ac227dcf..bcf7b498452 100644 --- a/src/EnergyPlus/CommandLineStringUtilities.hh +++ b/src/EnergyPlus/CommandLineStringUtilities.hh @@ -44,20 +44,88 @@ // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. -#include -#include -#include -#include +#include // for array +#include // for setlocale, LC_ALL +#include // for mbsrtowcs, wcsrtombs, wcslen, mbstate_t +#include // for path +#include // for runtime_error +#include // for string, wstring, operator+, to_string +#include // for is_same_v +#include // for forward namespace CLI { namespace detail { + + /// Attempt to set one of the acceptable unicode locales for conversion + inline void set_unicode_locale() + { + static const std::array unicode_locales{{"C.UTF-8", "en_US.UTF-8", ".UTF-8"}}; + + for (const auto &locale_name : unicode_locales) { + if (std::setlocale(LC_ALL, locale_name) != nullptr) { + return; + } + } + throw std::runtime_error("CLI::narrow: could not set locale to C.UTF-8"); + } + + template struct scope_guard_t + { + F closure; + + explicit scope_guard_t(F closure_) : closure(closure_) + { + } + ~scope_guard_t() + { + closure(); + } + }; + + // simple scope guard object, employs RAII to execute a callback when leaving scope, no matter if it's from a return or an exception + template inline scope_guard_t scope_guard(F &&closure) + { + return scope_guard_t{std::forward(closure)}; + } + inline std::string narrow_impl(const wchar_t *str, std::size_t str_size) { -#ifdef _WIN32 - return std::wstring_convert>().to_bytes(str, str + str_size); -#else - return std::wstring_convert>().to_bytes(str, str + str_size); -#endif + (void)str_size; + std::mbstate_t state = std::mbstate_t(); + const wchar_t *it = str; + + std::string old_locale = std::setlocale(LC_ALL, nullptr); // get current locale + auto sg = scope_guard([&] { std::setlocale(LC_ALL, old_locale.c_str()); }); // ensure we restore it even if we throw + set_unicode_locale(); + + std::size_t new_size = std::wcsrtombs(nullptr, &it, 0, &state); + if (new_size == static_cast(-1)) { + throw std::runtime_error("CLI::narrow: conversion error in std::wcsrtombs at offset " + std::to_string(it - str)); + } + std::string result(new_size, '\0'); + std::wcsrtombs(const_cast(result.data()), &str, new_size, &state); + + return result; + } + + inline std::wstring widen_impl(const char *str, std::size_t str_size) + { + (void)str_size; + std::mbstate_t state = std::mbstate_t(); + const char *it = str; + + std::string old_locale = std::setlocale(LC_ALL, nullptr); + auto sg = scope_guard([&] { std::setlocale(LC_ALL, old_locale.c_str()); }); + set_unicode_locale(); + + const std::size_t new_size = std::mbsrtowcs(nullptr, &it, 0, &state); + if (new_size == static_cast(-1)) { + throw std::runtime_error("CLI::widen: conversion error in std::mbsrtowcs at offset " + std::to_string(it - str)); + } + std::wstring result(new_size, L'\0'); + std::mbsrtowcs(const_cast(result.data()), &str, new_size, &state); + + return result; } } // namespace detail @@ -73,21 +141,19 @@ inline std::string narrow(const std::wstring &str) inline std::wstring widen(const std::string &str) { -#ifdef _WIN32 - return std::wstring_convert>().from_bytes(str.data(), str.data() + str.size()); -#else - return std::wstring_convert>().from_bytes(str.data(), str.data() + str.size()); -#endif // _WIN32 + return detail::widen_impl(str.data(), str.size()); +} +inline std::wstring widen(const char *str) +{ + return detail::widen_impl(str, std::strlen(str)); } inline std::filesystem::path to_path(const std::string &str) { - return { -#ifdef _WIN32 - widen(str) -#else - str -#endif // _WIN32 - }; + if constexpr (std::is_same_v) { + return {widen(str)}; + } else { + return {str}; + } } } // namespace CLI diff --git a/src/EnergyPlus/main.cc b/src/EnergyPlus/main.cc index dbd6fffc93a..243a7ec6d70 100644 --- a/src/EnergyPlus/main.cc +++ b/src/EnergyPlus/main.cc @@ -71,8 +71,9 @@ int wmain(int argc, wchar_t *wargv[]) std::vector args; args.reserve(wargs.size()); std::transform(wargs.cbegin(), wargs.cend(), std::back_inserter(args), [](const std::wstring &ws) { return CLI::narrow(ws); }); + int i = 0; for (const auto &wstr : wargs) { - fmt::print(L"wargs={}\n", wstr); + fmt::print(L"wargs[{}] = {}\n", i++, wstr); } fmt::print("args={}\n", args); @@ -91,6 +92,6 @@ int main(int argc, const char *argv[]) #endif std::vector args(argv, std::next(argv, static_cast(argc))); fmt::print("args={}\n", args); - return EnergyPlusPgm(std::move(args)); + return EnergyPlusPgm(args); } #endif From ad16f8744ae712775fcd0228f49db9fcfa357aaf Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Fri, 7 Jul 2023 15:41:14 +0200 Subject: [PATCH 13/26] WIP CLI11 --- src/ConvertInputFormat/main.cpp | 318 +- src/EnergyPlus/CommandLineInterface.cc | 392 +- src/EnergyPlus/CommandLineStringUtilities.hh | 159 - src/EnergyPlus/main.cc | 43 +- third_party/CLI/CLI11.hpp | 10278 +++++++++++++++++ third_party/CLI/LICENSE | 25 + third_party/CLI/MIT-LICENSE | 7 - third_party/CLI/README.md | 5 + third_party/CLI/ezOptionParser.hpp | 2159 ---- 9 files changed, 10595 insertions(+), 2791 deletions(-) delete mode 100644 src/EnergyPlus/CommandLineStringUtilities.hh create mode 100644 third_party/CLI/CLI11.hpp create mode 100644 third_party/CLI/LICENSE delete mode 100644 third_party/CLI/MIT-LICENSE create mode 100644 third_party/CLI/README.md delete mode 100644 third_party/CLI/ezOptionParser.hpp diff --git a/src/ConvertInputFormat/main.cpp b/src/ConvertInputFormat/main.cpp index 004633da347..c83e143e103 100644 --- a/src/ConvertInputFormat/main.cpp +++ b/src/ConvertInputFormat/main.cpp @@ -45,34 +45,50 @@ // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. -#include -#include -#ifdef _OPENMP -#include -#endif - #include "EnergyPlus/DataStringGlobals.hh" #include "EnergyPlus/FileSystem.hh" #include "EnergyPlus/InputProcessing/IdfParser.hh" #include "EnergyPlus/InputProcessing/InputValidation.hh" #include -#include + +#include +#include +#include #include +#ifdef _OPENMP +#include +#endif + +#include +#include +#include // for make_move_iterator +#include +#include +#include +#include +#include + using json = nlohmann::json; enum class OutputTypes { - Default, + Default = 0, IDF, epJSON, + // Experimental starting here CBOR, MsgPack, UBJSON, - BSON + BSON, + Num }; +static constexpr std::array(OutputTypes::Num)> outputTypeStrs = { + "default", "IDF", "epJSON", "CBOR", "MsgPack", "UBJSON", "BSON"}; -template void displayMessage(std::string_view str_format, Args &&... args) +static constexpr auto outputTypeExperimentalStart = OutputTypes::CBOR; + +template void displayMessage(std::string_view str_format, Args &&...args) { fmt::print(std::cout, str_format, args...); std::cout.write("\n", 1); @@ -260,7 +276,7 @@ void cleanEPJSON(json &epjson) } } -bool processInput(std::string const &inputFilePathStr, +bool processInput(fs::path const &inputFilePath, json const &schema, OutputTypes outputType, fs::path outputDirPath, @@ -271,7 +287,6 @@ bool processInput(std::string const &inputFilePathStr, auto idf_parser(std::make_unique()); json epJSON; - fs::path const inputFilePath{inputFilePathStr}; auto const inputDirPath = EnergyPlus::FileSystem::getParentDirectoryPath(inputFilePath); if (outputDirPath.empty()) { @@ -280,11 +295,11 @@ bool processInput(std::string const &inputFilePathStr, auto const inputFileType = EnergyPlus::FileSystem::getFileType(inputFilePath); - bool isEpJSON = EnergyPlus::FileSystem::is_all_json_type(inputFileType); - bool isCBOR = (inputFileType == EnergyPlus::FileSystem::FileTypes::CBOR); - bool isMsgPack = (inputFileType == EnergyPlus::FileSystem::FileTypes::MsgPack); - bool isUBJSON = (inputFileType == EnergyPlus::FileSystem::FileTypes::UBJSON); - bool isBSON = (inputFileType == EnergyPlus::FileSystem::FileTypes::BSON); + const bool isEpJSON = EnergyPlus::FileSystem::is_all_json_type(inputFileType); + const bool isCBOR = (inputFileType == EnergyPlus::FileSystem::FileTypes::CBOR); + const bool isMsgPack = (inputFileType == EnergyPlus::FileSystem::FileTypes::MsgPack); + const bool isUBJSON = (inputFileType == EnergyPlus::FileSystem::FileTypes::UBJSON); + const bool isBSON = (inputFileType == EnergyPlus::FileSystem::FileTypes::BSON); if (!(isEpJSON || EnergyPlus::FileSystem::is_idf_type(inputFileType))) { displayMessage("ERROR: Input file must have IDF, IMF, or epJSON extension."); @@ -388,203 +403,130 @@ bool processInput(std::string const &inputFilePathStr, return true; } -std::vector parse_input_paths(std::string const &input_paths_file) +std::vector parse_input_paths(fs::path const &inputFilePath) { - std::ifstream input_paths_stream(input_paths_file); + std::ifstream input_paths_stream(inputFilePath); if (!input_paths_stream.is_open()) { - displayMessage("Could not open file: {}", input_paths_file); + displayMessage("Could not open file: {}", inputFilePath.generic_string()); return {}; } - std::vector input_paths; + std::vector input_paths; std::string line; while (std::getline(input_paths_stream, line)) { if (line.empty()) { continue; } - input_paths.emplace_back(line); + fs::path input_file{line}; + if (!fs::is_regular_file(input_file)) { + // Fall back on searching in the same directory as the lstfile + input_file = inputFilePath.parent_path() / input_file; + if (!fs::is_regular_file(input_file)) { + displayMessage("Input file does not exist: {}", line); + continue; + } + } + input_paths.emplace_back(std::move(input_file)); } return input_paths; } -int main(int argc, const char *argv[]) +int main(/** [[maybe_unused]] int argc, [[maybe_unused]] const char *argv[] */) { - ez::ezOptionParser opt; - - opt.overview = "Run input file conversion tool"; - opt.syntax = "ConvertInputFormat [OPTIONS] input_file [input_file ..]"; - opt.example = "ConvertInputFormat in.idf\n\n"; - - opt.add("1", // Default. - false, // Required? - 1, // Number of args expected. - 0, // Delimiter if expecting multiple args. - "Number of threads", // Help description. - "-j" // Flag token. - ); - - opt.add("", // Default. - false, // Required? - 1, // Number of args expected. - 0, // Delimiter if expecting multiple args. - "Text file with list of input files to convert (newline delimited)", // Help description. - "-i", // Flag token. - "--input" // Flag token. - ); - - opt.add("", // Default. - false, // Required? - 1, // Number of args expected. - 0, // Delimiter if expecting multiple args. - "Output directory. Will use input file location by default.", // Help description. - "-o", // Flag token. - "--output" // Flag token. - ); - - const char *validOptions[] = {"default", "idf", "epjson", "json", "cbor", "msgpack", "ubjson", "bson"}; - auto *outputTypeValidation = new ez::ezOptionValidator(ez::ezOptionValidator::T, ez::ezOptionValidator::IN, validOptions, 8, true); - - opt.add("default", // Default. - 0, // Required? - 1, // Number of args expected. - 0, // Delimiter if expecting multiple args. - "Output format.\nDefault means IDF->epJSON or epJSON->IDF\nSelect one (case " - "insensitive):\ndefault,idf,epjson,json,cbor,msgpack,ubjson,bson", // Help description. - "-f", // Flag token. - "--format", // Flag token. - outputTypeValidation); - - opt.add("", // Default. - 0, // Required? - 0, // Number of args expected. - 0, // Delimiter if expecting multiple args. - "Do not convert HVACTemplate objects.", // Help description. - "-n", // Flag token. - "--noHVACTemplate" // Flag token. - ); - - opt.add("", 0, 0, 0, "Display version information", "-v", "--version"); - - opt.add("", // Default. - false, // Required? - 0, // Number of args expected. - 0, // Delimiter if expecting multiple args. - "Display usage instructions.", // Help description. - "-h", // Flag token. - "-help", // Flag token. - "--help", // Flag token. - "--usage" // Flag token. - ); - - opt.parse(argc, argv); - - std::string usage; - opt.getUsage(usage); - - // Process standard arguments - if (opt.isSet("-h")) { - displayMessage(usage); - exit(EXIT_SUCCESS); - } - - if (opt.isSet("-v")) { - displayMessage(EnergyPlus::DataStringGlobals::VerString); - exit(EXIT_SUCCESS); - } + CLI::App app{"ConvertInputFormat"}; + app.description("Run input file conversion tool"); + app.set_version_flag("--version", EnergyPlus::DataStringGlobals::VerString); +#ifdef _OPENMP + int number_of_threads = std::thread::hardware_concurrency(); +#else int number_of_threads = 1; - if (opt.isSet("-j")) { - opt.get("-j")->getInt(number_of_threads); +#endif + + [[maybe_unused]] CLI::Option *nproc_opt = + app.add_option("-j", number_of_threads, fmt::format("Number of threads [Default: {}]", number_of_threads))->option_text("N"); + #ifndef _OPENMP - displayMessage("ConvertInputFormat is not compiled with OpenMP. Only running on 1 thread, not requested {} threads.", number_of_threads); + // I don't want to throw if the user passes -j while OpenMP is unavailable, so we hide it by setting an empty group instead + nproc_opt->group(""); #endif - } - std::string output_directory; - if (opt.isSet("-o")) { - opt.get("-o")->getString(output_directory); - if (output_directory.back() != EnergyPlus::DataStringGlobals::pathChar) { - output_directory.push_back(EnergyPlus::DataStringGlobals::pathChar); - } - EnergyPlus::FileSystem::makeDirectory(output_directory); - } + fs::path inputFilePath; + app.add_option("-i,--input", inputFilePath, "Text file with list of input files to convert (newline delimited)") + ->required(false) + ->option_text("LSTFILE") + ->check(CLI::ExistingFile); - std::vector files; - if (opt.isSet("-i")) { - std::string input_paths_file; - opt.get("-i")->getString(input_paths_file); - files = parse_input_paths(input_paths_file); - } + fs::path outputDirectoryPath; + app.add_option("-o,--output", outputDirectoryPath, "Output directory. Will use input file location by default") + ->option_text("DIR") + ->required(false); + // ->check(CLI::ExistingDirectory) // We don't require it to exist, we make it if needed - bool convertHVACTemplate = true; - if (opt.isSet("-n")) { - convertHVACTemplate = false; - } + // opt.overview = "Run input file conversion tool"; + // opt.syntax = "ConvertInputFormat [OPTIONS] input_file [input_file ..]"; + // opt.example = "ConvertInputFormat in.idf\n\n"; - std::string outputTypeStr; - auto outputType = OutputTypes::Default; - if (opt.isSet("-f")) { - opt.get("-f")->getString(outputTypeStr); - std::transform(outputTypeStr.begin(), outputTypeStr.end(), outputTypeStr.begin(), ::toupper); - auto const buffer_view = std::string_view(outputTypeStr.data()); - if (buffer_view.compare(".EPJSON") == 0 || buffer_view.compare(".JSON") == 0) { - outputType = OutputTypes::epJSON; - outputTypeStr = "EPJSON"; - } else if (buffer_view.compare(".IDF") == 0 || buffer_view.compare(".IMF") == 0) { - outputType = OutputTypes::IDF; - } else if (buffer_view.compare(".CBOR") == 0) { - outputType = OutputTypes::CBOR; - displayMessage("CBOR input format is experimental."); - } else if (buffer_view.compare(".MSGPACK") == 0) { - outputType = OutputTypes::MsgPack; - displayMessage("MsgPack input format is experimental."); - } else if (buffer_view.compare(".UBJSON") == 0) { - outputType = OutputTypes::UBJSON; - displayMessage("UBJSON input format is experimental."); - } else if (buffer_view.compare(".BSON") == 0) { - outputType = OutputTypes::BSON; - displayMessage("BSON input format is experimental."); - } else { - displayMessage("ERROR: Output type must be IDF, epJSON, CBOR, MsgPack, UBJSON, or BSON."); - return 1; - } - } + const std::map outputTypeMap{ + {"default", OutputTypes::Default}, + {"idf", OutputTypes::IDF}, + {"epjson", OutputTypes::epJSON}, + {"cbor", OutputTypes::CBOR}, + {"msgpack", OutputTypes::MsgPack}, + {"ubjson", OutputTypes::UBJSON}, + {"bson", OutputTypes::BSON}, + }; - if (!opt.lastArgs.empty()) { - for (auto const &lastArg : opt.lastArgs) { - files.emplace_back(*lastArg); - } - } else if (opt.firstArgs.size() > 1) { - for (std::size_t i = 1; i < opt.firstArgs.size(); ++i) { - files.emplace_back(*opt.firstArgs[i]); - } + OutputTypes outputType{OutputTypes::Default}; + + const std::string help_message = fmt::format(R"help(Output format. +Default means IDF->epJSON or epJSON->IDF +Select one (case insensitive): +[{}])help", + fmt::join(outputTypeStrs, ",")); + + app.add_option("-f,--format", outputType, help_message) + ->option_text("FORMAT") + ->required(false) + ->transform(CLI::CheckedTransformer(outputTypeMap, CLI::ignore_case)); + + bool noConvertHVACTemplate = false; + app.add_flag("-n,--noHVACTemplate", noConvertHVACTemplate, "Do not convert HVACTemplate objects"); + + std::vector files; + app.add_option("input_file", files, "Multiple input files to be translated")->required(false)->check(CLI::ExistingFile); + + app.footer("Example: ConvertInputFormat in.idf"); + + // We are not modifying argc/argv, so we defer to CLI11 to find the argc/argv instead. It'll use GetCommandLineW & CommandLineToArgvW on windows + CLI11_PARSE(app); + + const bool convertHVACTemplate = !noConvertHVACTemplate; + + if (!outputDirectoryPath.empty()) { + EnergyPlus::FileSystem::makeDirectory(outputDirectoryPath); } - std::vector badOptions; - if (!opt.gotRequired(badOptions)) { - for (auto const &badOption : badOptions) { - fmt::print(std::cerr, "ERROR: Missing required option {}.\n\n", badOption); - } - displayMessage(usage); - return 1; + if (!inputFilePath.empty()) { + std::vector list_files = parse_input_paths(inputFilePath); + files.insert(files.end(), std::make_move_iterator(list_files.begin()), std::make_move_iterator(list_files.end())); } - if (!opt.gotExpected(badOptions)) { - for (auto const &badOption : badOptions) { - fmt::print(std::cerr, "ERROR: Got unexpected number of arguments for option {}.\n\n", badOption); - } - displayMessage(usage); - return 1; + std::string outputTypeStr{outputTypeStrs[static_cast(outputType)]}; + if (outputType >= outputTypeExperimentalStart) { + displayMessage("{} input format is experimental.", outputTypeStr); } - std::vector badArgs; - if (!opt.gotValid(badOptions, badArgs)) { - for (std::size_t i = 0; i < badOptions.size(); ++i) { - fmt::print(std::cerr, "ERROR: Got invalid argument \"{}\" for option {}.\n\n", badArgs[i], badOptions[i]); - } + if (files.empty()) { + displayMessage("No valid files found. Either specify --input or pass files as extra arguments"); return 1; } + // Must sort before unique + std::sort(files.begin(), files.end()); + auto it = std::unique(files.begin(), files.end()); + files.resize(std::distance(files.begin(), it)); + auto const embeddedEpJSONSchema = EnergyPlus::EmbeddedEpJSONSchema::embeddedEpJSONSchema(); auto schema = json::from_cbor(embeddedEpJSONSchema); @@ -593,14 +535,12 @@ int main(int argc, const char *argv[]) #ifdef _OPENMP omp_set_num_threads(number_of_threads); -#endif -#ifdef _OPENMP -#pragma omp parallel default(none) shared(files, number_files, fileCount, schema, outputType, outputTypeStr, output_directory, convertHVACTemplate) +#pragma omp parallel default(none) shared(files, number_files, fileCount, schema, outputType, outputTypeStr, outputDirectoryPath, convertHVACTemplate) { #pragma omp for for (int i = 0; i < number_files; ++i) { - bool successful = processInput(files[i], schema, outputType, output_directory, outputTypeStr, convertHVACTemplate); + const bool successful = processInput(files[i], schema, outputType, outputDirectoryPath, outputTypeStr, convertHVACTemplate); #pragma omp atomic ++fileCount; if (successful) { @@ -610,9 +550,15 @@ int main(int argc, const char *argv[]) } } } + #else + if (number_of_threads > 1) { + displayMessage("ConvertInputFormat is not compiled with OpenMP. Only running on 1 thread, not requested {} threads.", number_of_threads); + number_of_threads = 1; + } + for (auto const &file : files) { - bool successful = processInput(file, schema, outputType, output_directory, outputTypeStr, convertHVACTemplate); + bool successful = processInput(file, schema, outputType, outputDirectoryPath, outputTypeStr, convertHVACTemplate); ++fileCount; if (successful) { displayMessage("Input file converted to {} successfully | {}/{} | {}", outputTypeStr, fileCount, number_files, file); diff --git a/src/EnergyPlus/CommandLineInterface.cc b/src/EnergyPlus/CommandLineInterface.cc index 4d110b8df70..39c2509f914 100644 --- a/src/EnergyPlus/CommandLineInterface.cc +++ b/src/EnergyPlus/CommandLineInterface.cc @@ -49,7 +49,7 @@ #include // CLI Headers -#include +#include // Project headers #include @@ -67,11 +67,9 @@ namespace EnergyPlus { namespace CommandLineInterface { - using namespace ez; - int ProcessArgs(EnergyPlusData &state, const std::vector &args) { - typedef std::string::size_type size_type; + using size_type = std::string::size_type; // Expand long-name options using "=" sign in to two arguments // and expand multiple short options into separate arguments @@ -96,203 +94,171 @@ namespace CommandLineInterface { } } - // Define options - ezOptionParser opt; - - opt.overview = state.dataStrGlobals->VerStringVar; - opt.overview.append("\nPythonLinkage: " + PluginManagement::pythonStringForUsage(state)); - opt.overview.append("\nBuilt on Platform: " + DataStringGlobals::BuildPlatformString); - - opt.syntax = "energyplus [options] [input-file]"; - - opt.add("", 0, 0, 0, "Force annual simulation", "-a", "--annual"); - - opt.add("", 0, 1, 0, "Output directory path (default: current directory)", "-d", "--output-directory"); - - opt.add("", 0, 0, 0, "Force design-day-only simulation", "-D", "--design-day"); - - opt.add("", 0, 0, 0, "Display help information", "-h", "--help"); - - opt.add("Energy+.idd", 0, 1, 0, "Input data dictionary path (default: Energy+.idd in executable directory)", "-i", "--idd"); - - opt.add("", 0, 0, 0, "Run EPMacro prior to simulation", "-m", "--epmacro"); - - opt.add("", 0, 1, 0, "Prefix for output file names (default: eplus)", "-p", "--output-prefix"); - - opt.add("", 0, 0, 0, "Run ReadVarsESO after simulation", "-r", "--readvars"); - - opt.add("", 0, 0, 0, "Output IDF->epJSON or epJSON->IDF, dependent on input file type", "-c", "--convert"); - - opt.add("", 0, 0, 0, "Only convert IDF->epJSON or epJSON->IDF, dependent on input file type. No simulation", "--convert-only"); - - opt.add("L", - 0, - 1, - 0, - "Suffix style for output file names (default: L)\n L: Legacy (e.g., eplustbl.csv)\n C: Capital (e.g., eplusTable.csv)\n D: " - "Dash (e.g., eplus-table.csv)", - "-s", - "--output-suffix"); - - opt.add("", false, 0, 0, "Display version information", "-v", "--version"); - - opt.add("1", false, 1, 0, "Multi-thread with N threads; 1 thread with no arg. (Currently only for G-Function generation)", "-j", "--jobs"); - - opt.add("in.epw", false, 1, 0, "Weather file path (default: in.epw in current directory)", "-w", "--weather"); - - opt.add("", false, 0, 0, "Run ExpandObjects prior to simulation", "-x", "--expandobjects"); - - opt.example = "energyplus -w weather.epw -r input.idf"; - - const std::string errorFollowUp = "Type 'energyplus --help' for usage."; - - // Fix This is problematic for a few reasons: - // Using ezOptionParser with a raw C-string interface is asking for trouble: Find something taking std::string if possible - // Passing out pointers returned by c_str() is bad form: - // They are pointers to internally-managed memory in std::string - // They are invalid as soon as the string goes out of scope or is modified - // In this case the strings may be in scope and unmodified until parse is done but this is red flag usage - // convert to vector of C strings for option parser - std::vector cStrArgs; - cStrArgs.reserve(arguments.size()); - for (const auto &argument : arguments) { - cStrArgs.push_back(argument.c_str()); - } - size_type const argCount = arguments.size(); - bool const legacyMode = (argCount == 1); - // Parse arguments - opt.parse(static_cast(argCount), cStrArgs.data()); - - // print arguments parsed (useful for debugging) - // std::string pretty; - // opt.prettyPrint(pretty); - // std::cout << pretty << std::endl; - - std::string usage; - opt.getUsage(usage); - // Set path of EnergyPlus program path (if we aren't overriding it) if (!state.dataGlobal->installRootOverride) { state.dataStrGlobals->exeDirectoryPath = FileSystem::getParentDirectoryPath(FileSystem::getAbsolutePath(FileSystem::getProgramPath())); } - // ezOptionParser doesn't have a getPath, so we get a string, then convert it to path - // I'm limiting the scope of the std::string temporaries I used to avoid mistakes - { - std::string inputWeatherFileName; - opt.get("-w")->getString(inputWeatherFileName); - state.files.inputWeatherFilePath.filePath = CLI::to_path(inputWeatherFileName); - } - - { - // TODO: should this be in IOFiles as an InputFile? - std::string inputIddFileName; - opt.get("-i")->getString(inputIddFileName); - state.dataStrGlobals->inputIddFilePath = CLI::to_path(inputIddFileName); - } - - if (!opt.isSet("-i") && !legacyMode) { - state.dataStrGlobals->inputIddFilePath = state.dataStrGlobals->exeDirectoryPath / state.dataStrGlobals->inputIddFilePath; - } - - { - std::string outDirPathName; - opt.get("-d")->getString(outDirPathName); - state.dataStrGlobals->outDirPath = CLI::to_path(outDirPathName); - } - - state.dataGlobal->runReadVars = opt.isSet("-r"); - - state.dataGlobal->DDOnlySimulation = opt.isSet("-D"); + CLI::App app{"energyplus"}; + // opt.add("", false, 0, 0, "Display version information", "-v", "--version"); + app.set_version_flag("--version", EnergyPlus::DataStringGlobals::VerString); - state.dataGlobal->AnnualSimulation = opt.isSet("-a"); + // opt.overview = state.dataStrGlobals->VerStringVar; + // opt.overview.append("\nPythonLinkage: " + PluginManagement::pythonStringForUsage(state)); + // opt.overview.append("\nBuilt on Platform: " + DataStringGlobals::BuildPlatformString); - state.dataGlobal->outputEpJSONConversion = opt.isSet("-c"); + std::string const description = fmt::format(R"({} +PythonLinkage: {} +Built on Platform: {} +)", + state.dataStrGlobals->VerStringVar, + PluginManagement::pythonStringForUsage(state), + DataStringGlobals::BuildPlatformString); - state.dataGlobal->outputEpJSONConversionOnly = opt.isSet("--convert-only"); + // opt.add("", 0, 0, 0, "Force annual simulation", "-a", "--annual"); + app.add_flag("-a,--annual", state.dataGlobal->AnnualSimulation, "Force annual simulation"); - bool eplusRunningViaAPI = state.dataGlobal->eplusRunningViaAPI; - - opt.get("-j")->getInt(state.dataGlobal->numThread); - - if (state.dataGlobal->numThread == 0) { - DisplayString(state, "Invalid value for -j arg. Defaulting to 1."); - state.dataGlobal->numThread = 1; - } else if (state.dataGlobal->numThread > (int)std::thread::hardware_concurrency()) { - DisplayString(state, - fmt::format("Invalid value for -j arg. Value exceeds num available. Defaulting to num available. -j {}", - (int)std::thread::hardware_concurrency())); - state.dataGlobal->numThread = (int)std::thread::hardware_concurrency(); - } + // opt.add("", 0, 1, 0, "Output directory path (default: current directory)", "-d", "--output-directory"); + app.add_option("-d,--output-directory", state.dataStrGlobals->outDirPath, "Output directory path (default: current directory)") + ->option_text("DIR") + ->required(false); + // ->check(CLI::ExistingDirectory) // We don't require it to exist, we make it if needed - // Process standard arguments - if (opt.isSet("-h")) { - DisplayString(state, usage); - if (eplusRunningViaAPI) { - // we need another return code to let runEnergyPlusAsLibrary know it should not try to run anything - return static_cast(ReturnCodes::SuccessButHelper); - } else { - exit(EXIT_SUCCESS); - } - } + // opt.add("", 0, 0, 0, "Force design-day-only simulation", "-D", "--design-day"); + app.add_flag("-D,--design-day", state.dataGlobal->DDOnlySimulation, "Force design-day-only simulation"); - if (opt.isSet("-v")) { - DisplayString(state, state.dataStrGlobals->VerStringVar); + // opt.add("Energy+.idd", 0, 1, 0, "Input data dictionary path (default: Energy+.idd in executable directory)", "-i", "--idd"); + if (legacyMode) { + state.dataStrGlobals->inputIddFilePath = "Energy+.idd"; + } else { + state.dataStrGlobals->inputIddFilePath = state.dataStrGlobals->exeDirectoryPath / "Energy+.idd"; + } + app.add_option( + "-i,--idd", state.dataStrGlobals->inputIddFilePath, "Input data dictionary path (default: Energy+.idd in executable directory)") + ->required(false) + ->option_text("IDD") + ->check(CLI::ExistingFile); + + // opt.add("", 0, 0, 0, "Run EPMacro prior to simulation", "-m", "--epmacro"); + bool runEPMacro = false; + app.add_flag("-m,--epmacro", runEPMacro, "Run EPMacro prior to simulation"); + + // opt.add("", 0, 1, 0, "Prefix for output file names (default: eplus)", "-p", "--output-prefix"); + std::string prefixOutName = "eplus"; + app.add_option("-p,--output-prefix", prefixOutName, "Prefix for output file names (default: eplus)")->required(false)->option_text("PRE"); + + // opt.add("", 0, 0, 0, "Run ReadVarsESO after simulation", "-r", "--readvars"); + app.add_flag("-r,--readvars", state.dataGlobal->runReadVars, "Run ReadVarsESO after simulation"); + + // opt.add("", 0, 0, 0, "Output IDF->epJSON or epJSON->IDF, dependent on input file type", "-c", "--convert"); + app.add_flag("-c,--convert", state.dataGlobal->outputEpJSONConversion, "Output IDF->epJSON or epJSON->IDF, dependent on input file type"); + + // opt.add("", 0, 0, 0, "Only convert IDF->epJSON or epJSON->IDF, dependent on input file type. No simulation", "--convert-only"); + app.add_flag("--convert-only", + state.dataGlobal->outputEpJSONConversionOnly, + "Only convert IDF->epJSON or epJSON->IDF, dependent on input file type. No simulation"); + + // opt.add("L", + // 0, + // 1, + // 0, + //"Suffix style for output file names (default: L)\n L: Legacy (e.g., eplustbl.csv)\n C: Capital (e.g., eplusTable.csv)\n D: " + //"Dash (e.g., eplus-table.csv)", + //"-s", + //"--output-suffix"); + // TODO: make it an enum instead? + std::string suffixType = "L"; + std::string const suffixHelp = R"help(Suffix style for output file names (default: L) + L: Legacy (e.g., eplustbl.csv) + C: Capital (e.g., eplusTable.csv) + D: Dash (e.g., eplus-table.csv))help"; + app.add_option("-s,--output-suffix", state.dataGlobal->outputEpJSONConversion, suffixHelp) + ->option_text("SUFFIX") + ->required(false) + ->check(CLI::IsMember({"L", "C", "D"}, CLI::ignore_case)); + + // opt.add("1", false, 1, 0, "Multi-thread with N threads; 1 thread with no arg. (Currently only for G-Function generation)", "-j", "--jobs"); + // TODO: maybe delay validation to output a better error message? + const int MAX_N = static_cast(std::thread::hardware_concurrency()); + app.add_option("-j,--jobs", + state.dataGlobal->numThread, + "Multi-thread with N threads; 1 thread with no arg. (Currently only for G-Function generation)") + ->option_text("N") + ->transform([MAX_N, &state](std::string input) -> std::string { + int number_of_threads = -1; + bool const converted = CLI::detail::lexical_cast(input, number_of_threads); + if (!converted) { + // CLI::ValidationError + return std::string{}; + } + if (number_of_threads <= 0) { + DisplayString(state, "Invalid value for -j arg. Defaulting to 1."); + return "1"; + } + if (number_of_threads > MAX_N) { + DisplayString(state, + fmt::format("Invalid value for -j arg. Value exceeds num available. Defaulting to num available. -j {}", MAX_N)); + return std::to_string(MAX_N); + } + return std::string{}; + }); + + // if (state.dataGlobal->numThread == 0) { + // DisplayString(state, "Invalid value for -j arg. Defaulting to 1."); + // state.dataGlobal->numThread = 1; + // } else if (state.dataGlobal->numThread > (int)std::thread::hardware_concurrency()) { + // DisplayString(state, + // fmt::format("Invalid value for -j arg. Value exceeds num available. Defaulting to num available. -j {}", + // (int)std::thread::hardware_concurrency())); + // state.dataGlobal->numThread = (int)std::thread::hardware_concurrency(); + // } + + // opt.add("in.epw", false, 1, 0, "Weather file path (default: in.epw in current directory)", "-w", "--weather"); + state.files.inputWeatherFilePath.filePath = "in.epw"; + app.add_option("-w,--weather", state.files.inputWeatherFilePath.filePath, "Weather file path (default: in.epw in current directory)") + ->required(false) + ->option_text("EPW") + ->check(CLI::ExistingFile); + + // opt.add("", false, 0, 0, "Run ExpandObjects prior to simulation", "-x", "--expandobjects"); + bool runExpandObjects = false; + app.add_flag("-x,--expandobjects", runExpandObjects, "Run ExpandObjects prior to simulation"); + + // Positional + state.dataStrGlobals->inputFilePath = "in.idf"; + app.add_option("input_file", state.dataStrGlobals->inputFilePath, "Input file (default: in.idf in current directory)") + ->required(false) + ->check(CLI::ExistingFile); + + // opt.example = "energyplus -w weather.epw -r input.idf"; + app.footer("energyplus -w weather.epw -r input.idf"); + + const bool eplusRunningViaAPI = state.dataGlobal->eplusRunningViaAPI; + + try { + // app.parse(argc, argv); + // CLI11 when passing argc, argv creates a vector but **in reverse** order: + // https://github.com/CLIUtils/CLI11/blob/291c58789c031208f08f4f261a858b5b7083e8e2/include/CLI/impl/App_inl.hpp#L476-L488 + std::reverse(args.begin(), args.end()); + app.parse(args); + } catch (const CLI::ParseError &e) { if (eplusRunningViaAPI) { - // we need another return code to let runEnergyPlusAsLibrary know it should not try to run anything - return static_cast(ReturnCodes::SuccessButHelper); + DisplayString(state, fmt::format("{}: {}", e.get_name(), e.what())); + return static_cast(ReturnCodes::Failure); } else { - exit(EXIT_SUCCESS); + return app.exit(e); } } - if (opt.lastArgs.size() == 1) { - state.dataStrGlobals->inputFilePath = CLI::to_path(*opt.lastArgs[0]); - } else if (opt.lastArgs.empty()) { - state.dataStrGlobals->inputFilePath = "in.idf"; - } - // Convert all paths to native paths state.dataStrGlobals->inputFilePath = FileSystem::makeNativePath(state.dataStrGlobals->inputFilePath); state.files.inputWeatherFilePath.filePath = FileSystem::makeNativePath(state.files.inputWeatherFilePath.filePath); state.dataStrGlobals->inputIddFilePath = FileSystem::makeNativePath(state.dataStrGlobals->inputIddFilePath); state.dataStrGlobals->outDirPath = FileSystem::makeNativePath(state.dataStrGlobals->outDirPath); - std::vector badOptions; - if (opt.lastArgs.size() > 1u) { - bool invalidOptionFound = false; - for (size_type i = 0; i < opt.lastArgs.size(); ++i) { - std::string const &arg(*opt.lastArgs[i]); - if (arg.substr(0, 1) == "-") { - invalidOptionFound = true; - DisplayString(state, "ERROR: Invalid option: " + arg); - } - } - if (invalidOptionFound) { - DisplayString(state, errorFollowUp); - if (eplusRunningViaAPI) { - return static_cast(ReturnCodes::Failure); - } else { - exit(EXIT_FAILURE); - } - } else { - DisplayString(state, "ERROR: Multiple input files specified:"); - for (size_type i = 0; i < opt.lastArgs.size(); ++i) { - std::string const &arg(*opt.lastArgs[i]); - DisplayString(state, format(" Input file #{}: {}", i + 1, arg)); - } - DisplayString(state, errorFollowUp); - if (eplusRunningViaAPI) { - return static_cast(ReturnCodes::Failure); - } else { - exit(EXIT_FAILURE); - } - } - } - state.dataStrGlobals->inputFilePathNameOnly = FileSystem::getFileName(state.dataStrGlobals->inputFilePath); state.dataStrGlobals->inputDirPath = FileSystem::getParentDirectoryPath(state.dataStrGlobals->inputFilePath); @@ -327,24 +293,14 @@ namespace CommandLineInterface { } } - bool runExpandObjects = opt.isSet("-x"); - bool runEPMacro = opt.isSet("-m"); - - if (opt.isSet("-d")) { + if (!state.dataStrGlobals->outDirPath.empty()) { // Create directory if it doesn't already exist FileSystem::makeDirectory(state.dataStrGlobals->outDirPath); } // File naming scheme - fs::path outputFilePrefixFullPath; - if (opt.isSet("-p")) { - std::string prefixOutName; - opt.get("-p")->getString(prefixOutName); - fs::path prefix = FileSystem::makeNativePath(fs::path(prefixOutName)); // Why is this needed? - outputFilePrefixFullPath = state.dataStrGlobals->outDirPath / prefixOutName; - } else { - outputFilePrefixFullPath = state.dataStrGlobals->outDirPath / "eplus"; - } + fs::path const prefix = FileSystem::makeNativePath(fs::path(prefixOutName)); // Why is this needed? + fs::path outputFilePrefixFullPath = state.dataStrGlobals->outDirPath / prefixOutName; fs::path outputEpmdetFilePath; fs::path outputEpmidfFilePath; @@ -363,10 +319,9 @@ namespace CommandLineInterface { std::string screenSuffix; std::string shdSuffix; - std::string suffixType; + std::string const errorFollowUp = "Type 'energyplus --help' for usage."; { - opt.get("-s")->getString(suffixType); - std::transform((suffixType).begin(), (suffixType).end(), (suffixType).begin(), ::toupper); + std::transform(suffixType.begin(), suffixType.end(), suffixType.begin(), ::toupper); if (suffixType == "L") { @@ -406,16 +361,8 @@ namespace CommandLineInterface { adsSuffix = "Ads"; screenSuffix = "Screen"; shdSuffix = "Shading"; - - } else { - DisplayString(state, "ERROR: Unrecognized argument for output suffix style: " + suffixType); - DisplayString(state, errorFollowUp); - if (eplusRunningViaAPI) { - return static_cast(ReturnCodes::Failure); - } else { - exit(EXIT_FAILURE); - } } + // No else needed, this is validated at CLI level above } // Helper to construct output file path @@ -529,49 +476,6 @@ namespace CommandLineInterface { outputExpidfFilePath = composePath(normalSuffix + ".expidf"); outputExperrFilePath = composePath(normalSuffix + ".experr"); - // Handle bad options - if (!opt.gotExpected(badOptions)) { - for (size_type i = 0; i < badOptions.size(); ++i) { - DisplayString(state, "ERROR: Unexpected number of arguments for option " + badOptions[i]); - } - DisplayString(state, errorFollowUp); - if (eplusRunningViaAPI) { - return static_cast(ReturnCodes::Failure); - } else { - exit(EXIT_FAILURE); - } - } - - // This is a placeholder in case there are required options in the future - if (!opt.gotRequired(badOptions)) { - for (size_type i = 0; i < badOptions.size(); ++i) { - DisplayString(state, "ERROR: Missing required option " + badOptions[i]); - } - DisplayString(state, errorFollowUp); - if (eplusRunningViaAPI) { - return static_cast(ReturnCodes::Failure); - } else { - exit(EXIT_FAILURE); - } - } - - if (opt.firstArgs.size() > 1 || opt.unknownArgs.size() > 0) { - for (size_type i = 1; i < opt.firstArgs.size(); ++i) { - std::string const &arg(*opt.firstArgs[i]); - DisplayString(state, "ERROR: Invalid option: " + arg); - } - for (size_type i = 0; i < opt.unknownArgs.size(); ++i) { - std::string const &arg(*opt.unknownArgs[i]); - DisplayString(state, "ERROR: Invalid option: " + arg); - } - DisplayString(state, errorFollowUp); - if (eplusRunningViaAPI) { - return static_cast(ReturnCodes::Failure); - } else { - exit(EXIT_FAILURE); - } - } - // Error for cases where both design-day and annual simulation switches are set if (state.dataGlobal->DDOnlySimulation && state.dataGlobal->AnnualSimulation) { DisplayString(state, "ERROR: Cannot force both design-day and annual simulations. Set either '-D' or '-a', but not both."); diff --git a/src/EnergyPlus/CommandLineStringUtilities.hh b/src/EnergyPlus/CommandLineStringUtilities.hh deleted file mode 100644 index bcf7b498452..00000000000 --- a/src/EnergyPlus/CommandLineStringUtilities.hh +++ /dev/null @@ -1,159 +0,0 @@ -// The Regents of the University of California, through Lawrence Berkeley National Laboratory -// (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge -// National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other -// contributors. All rights reserved. -// -// NOTICE: This Software was developed under funding from the U.S. Department of Energy and the -// U.S. Government consequently retains certain rights. As such, the U.S. Government has been -// granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable, -// worldwide license in the Software to reproduce, distribute copies to the public, prepare -// derivative works, and perform publicly and display publicly, and to permit others to do so. -// -// Redistribution and use in source and binary forms, with or without modification, are permitted -// provided that the following conditions are met: -// -// (1) Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// (2) Redistributions in binary form must reproduce the above copyright notice, this list of -// conditions and the following disclaimer in the documentation and/or other materials -// provided with the distribution. -// -// (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory, -// the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific prior -// written permission. -// -// (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form -// without changes from the version obtained under this License, or (ii) Licensee makes a -// reference solely to the software portion of its product, Licensee must refer to the -// software as "EnergyPlus version X" software, where "X" is the version number Licensee -// obtained under this License and may not use a different name for the software. Except as -// specifically required in this Section (4), Licensee shall not use in a company name, a -// product name, in advertising, publicity, or other promotional activities any name, trade -// name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly -// similar designation, without the U.S. Department of Energy's prior written consent. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR -// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#include // for array -#include // for setlocale, LC_ALL -#include // for mbsrtowcs, wcsrtombs, wcslen, mbstate_t -#include // for path -#include // for runtime_error -#include // for string, wstring, operator+, to_string -#include // for is_same_v -#include // for forward - -namespace CLI { -namespace detail { - - /// Attempt to set one of the acceptable unicode locales for conversion - inline void set_unicode_locale() - { - static const std::array unicode_locales{{"C.UTF-8", "en_US.UTF-8", ".UTF-8"}}; - - for (const auto &locale_name : unicode_locales) { - if (std::setlocale(LC_ALL, locale_name) != nullptr) { - return; - } - } - throw std::runtime_error("CLI::narrow: could not set locale to C.UTF-8"); - } - - template struct scope_guard_t - { - F closure; - - explicit scope_guard_t(F closure_) : closure(closure_) - { - } - ~scope_guard_t() - { - closure(); - } - }; - - // simple scope guard object, employs RAII to execute a callback when leaving scope, no matter if it's from a return or an exception - template inline scope_guard_t scope_guard(F &&closure) - { - return scope_guard_t{std::forward(closure)}; - } - - inline std::string narrow_impl(const wchar_t *str, std::size_t str_size) - { - (void)str_size; - std::mbstate_t state = std::mbstate_t(); - const wchar_t *it = str; - - std::string old_locale = std::setlocale(LC_ALL, nullptr); // get current locale - auto sg = scope_guard([&] { std::setlocale(LC_ALL, old_locale.c_str()); }); // ensure we restore it even if we throw - set_unicode_locale(); - - std::size_t new_size = std::wcsrtombs(nullptr, &it, 0, &state); - if (new_size == static_cast(-1)) { - throw std::runtime_error("CLI::narrow: conversion error in std::wcsrtombs at offset " + std::to_string(it - str)); - } - std::string result(new_size, '\0'); - std::wcsrtombs(const_cast(result.data()), &str, new_size, &state); - - return result; - } - - inline std::wstring widen_impl(const char *str, std::size_t str_size) - { - (void)str_size; - std::mbstate_t state = std::mbstate_t(); - const char *it = str; - - std::string old_locale = std::setlocale(LC_ALL, nullptr); - auto sg = scope_guard([&] { std::setlocale(LC_ALL, old_locale.c_str()); }); - set_unicode_locale(); - - const std::size_t new_size = std::mbsrtowcs(nullptr, &it, 0, &state); - if (new_size == static_cast(-1)) { - throw std::runtime_error("CLI::widen: conversion error in std::mbsrtowcs at offset " + std::to_string(it - str)); - } - std::wstring result(new_size, L'\0'); - std::mbsrtowcs(const_cast(result.data()), &str, new_size, &state); - - return result; - } -} // namespace detail - -inline std::string narrow(const wchar_t *str) -{ - return detail::narrow_impl(str, std::wcslen(str)); -} - -inline std::string narrow(const std::wstring &str) -{ - return detail::narrow_impl(str.data(), str.size()); -} - -inline std::wstring widen(const std::string &str) -{ - return detail::widen_impl(str.data(), str.size()); -} -inline std::wstring widen(const char *str) -{ - return detail::widen_impl(str, std::strlen(str)); -} - -inline std::filesystem::path to_path(const std::string &str) -{ - if constexpr (std::is_same_v) { - return {widen(str)}; - } else { - return {str}; - } -} -} // namespace CLI diff --git a/src/EnergyPlus/main.cc b/src/EnergyPlus/main.cc index 243a7ec6d70..54eacccf167 100644 --- a/src/EnergyPlus/main.cc +++ b/src/EnergyPlus/main.cc @@ -48,50 +48,21 @@ // EnergyPlus Headers #include -// C++ Headers -#include -#include -#include -#include - -#include -#include - -#ifdef _WIN32 -// EnergyPlus Headers -#include -#include - -int wmain(int argc, wchar_t *wargv[]) -{ - for (int i = 0; i < argc; ++i) { - fmt::print(L"wargv[{}] = {}\n", i, wargv[i]); - } - std::vector wargs(wargv, std::next(wargv, static_cast(argc))); - std::vector args; - args.reserve(wargs.size()); - std::transform(wargs.cbegin(), wargs.cend(), std::back_inserter(args), [](const std::wstring &ws) { return CLI::narrow(ws); }); - int i = 0; - for (const auto &wstr : wargs) { - fmt::print(L"wargs[{}] = {}\n", i++, wstr); - } - fmt::print("args={}\n", args); - - return EnergyPlusPgm(args); -} -#else +#include #ifdef DEBUG_ARITHM_GCC_OR_CLANG #include #endif -int main(int argc, const char *argv[]) +int main() { #ifdef DEBUG_ARITHM_GCC_OR_CLANG feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW); #endif - std::vector args(argv, std::next(argv, static_cast(argc))); - fmt::print("args={}\n", args); + + int const argc = CLI::argc(); + const char *const *argv = CLI::argv(); + + const std::vector args(argv, std::next(argv, static_cast(argc))); return EnergyPlusPgm(args); } -#endif diff --git a/third_party/CLI/CLI11.hpp b/third_party/CLI/CLI11.hpp new file mode 100644 index 00000000000..e2437d5e8f0 --- /dev/null +++ b/third_party/CLI/CLI11.hpp @@ -0,0 +1,10278 @@ +// CLI11: Version 2.3.2 +// Originally designed by Henry Schreiner +// https://github.com/CLIUtils/CLI11 +// +// This is a standalone header file generated by MakeSingleHeader.py in CLI11/scripts +// from: v2.3.2-34-g985a19f +// +// CLI11 2.3.2 Copyright (c) 2017-2023 University of Cincinnati, developed by Henry +// Schreiner under NSF AWARD 1414736. All rights reserved. +// +// Redistribution and use in source and binary forms of CLI11, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holder nor the names of its contributors +// may be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#pragma once + +// Standard combined includes: +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define CLI11_VERSION_MAJOR 2 +#define CLI11_VERSION_MINOR 3 +#define CLI11_VERSION_PATCH 2 +#define CLI11_VERSION "2.3.2" + + + + +// The following version macro is very similar to the one in pybind11 +#if !(defined(_MSC_VER) && __cplusplus == 199711L) && !defined(__INTEL_COMPILER) +#if __cplusplus >= 201402L +#define CLI11_CPP14 +#if __cplusplus >= 201703L +#define CLI11_CPP17 +#if __cplusplus > 201703L +#define CLI11_CPP20 +#endif +#endif +#endif +#elif defined(_MSC_VER) && __cplusplus == 199711L +// MSVC sets _MSVC_LANG rather than __cplusplus (supposedly until the standard is fully implemented) +// Unless you use the /Zc:__cplusplus flag on Visual Studio 2017 15.7 Preview 3 or newer +#if _MSVC_LANG >= 201402L +#define CLI11_CPP14 +#if _MSVC_LANG > 201402L && _MSC_VER >= 1910 +#define CLI11_CPP17 +#if _MSVC_LANG > 201703L && _MSC_VER >= 1910 +#define CLI11_CPP20 +#endif +#endif +#endif +#endif + +#if defined(CLI11_CPP14) +#define CLI11_DEPRECATED(reason) [[deprecated(reason)]] +#elif defined(_MSC_VER) +#define CLI11_DEPRECATED(reason) __declspec(deprecated(reason)) +#else +#define CLI11_DEPRECATED(reason) __attribute__((deprecated(reason))) +#endif + +// GCC < 10 doesn't ignore this in unevaluated contexts +#if !defined(CLI11_CPP17) || \ + (defined(__GNUC__) && !defined(__llvm__) && !defined(__INTEL_COMPILER) && __GNUC__ < 10 && __GNUC__ > 4) +#define CLI11_NODISCARD +#else +#define CLI11_NODISCARD [[nodiscard]] +#endif + +/** detection of rtti */ +#ifndef CLI11_USE_STATIC_RTTI +#if(defined(_HAS_STATIC_RTTI) && _HAS_STATIC_RTTI) +#define CLI11_USE_STATIC_RTTI 1 +#elif defined(__cpp_rtti) +#if(defined(_CPPRTTI) && _CPPRTTI == 0) +#define CLI11_USE_STATIC_RTTI 1 +#else +#define CLI11_USE_STATIC_RTTI 0 +#endif +#elif(defined(__GCC_RTTI) && __GXX_RTTI) +#define CLI11_USE_STATIC_RTTI 0 +#else +#define CLI11_USE_STATIC_RTTI 1 +#endif +#endif + +/** availability */ +#if defined CLI11_CPP17 && defined __has_include && !defined CLI11_HAS_FILESYSTEM +#if __has_include() +// Filesystem cannot be used if targeting macOS < 10.15 +#if defined __MAC_OS_X_VERSION_MIN_REQUIRED && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 +#define CLI11_HAS_FILESYSTEM 0 +#elif defined(__wasi__) +// As of wasi-sdk-14, filesystem is not implemented +#define CLI11_HAS_FILESYSTEM 0 +#else +#include +#if defined __cpp_lib_filesystem && __cpp_lib_filesystem >= 201703 +#if defined _GLIBCXX_RELEASE && _GLIBCXX_RELEASE >= 9 +#define CLI11_HAS_FILESYSTEM 1 +#elif defined(__GLIBCXX__) +// if we are using gcc and Version <9 default to no filesystem +#define CLI11_HAS_FILESYSTEM 0 +#else +#define CLI11_HAS_FILESYSTEM 1 +#endif +#else +#define CLI11_HAS_FILESYSTEM 0 +#endif +#endif +#endif +#endif + +/** availability */ +#if defined(__GNUC__) && !defined(__llvm__) && !defined(__INTEL_COMPILER) && __GNUC__ < 5 +#define CLI11_HAS_CODECVT 0 +#else +#define CLI11_HAS_CODECVT 1 +#include +#endif + +/** disable deprecations */ +#if defined(__GNUC__) // GCC or clang +#define CLI11_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") +#define CLI11_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") + +#define CLI11_DIAGNOSTIC_IGNORE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") + +#elif defined(_MSC_VER) +#define CLI11_DIAGNOSTIC_PUSH __pragma(warning(push)) +#define CLI11_DIAGNOSTIC_POP __pragma(warning(pop)) + +#define CLI11_DIAGNOSTIC_IGNORE_DEPRECATED __pragma(warning(disable : 4996)) + +#else +#define CLI11_DIAGNOSTIC_PUSH +#define CLI11_DIAGNOSTIC_POP + +#define CLI11_DIAGNOSTIC_IGNORE_DEPRECATED + +#endif + +/** Inline macro **/ +#ifdef CLI11_COMPILE +#define CLI11_INLINE +#else +#define CLI11_INLINE inline +#endif + + + +#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0 +#include // NOLINT(build/include) +#else +#include +#include +#endif + + + + +#ifdef CLI11_CPP17 +#include +#endif // CLI11_CPP17 + +#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0 +#include +#include // NOLINT(build/include) +#endif // CLI11_HAS_FILESYSTEM + + + +#if defined(_WIN32) +#if !(defined(_AMD64_) || defined(_X86_) || defined(_ARM_)) +#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || \ + defined(_M_AMD64) +#define _AMD64_ +#elif defined(i386) || defined(__i386) || defined(__i386__) || defined(__i386__) || defined(_M_IX86) +#define _X86_ +#elif defined(__arm__) || defined(_M_ARM) || defined(_M_ARMT) +#define _ARM_ +#endif +#endif + +// first +#ifndef NOMINMAX +// if NOMINMAX is already defined we don't want to mess with that either way +#define NOMINMAX +#include +#undef NOMINMAX +#else +#include +#endif + +// second +#include +// third +#include +#include + +#elif defined(__APPLE__) +#include +#endif + + +namespace CLI { + + +/// Convert a wide string to a narrow string. +CLI11_INLINE std::string narrow(const std::wstring &str); +CLI11_INLINE std::string narrow(const wchar_t *str); +CLI11_INLINE std::string narrow(const wchar_t *str, std::size_t size); + +/// Convert a narrow string to a wide string. +CLI11_INLINE std::wstring widen(const std::string &str); +CLI11_INLINE std::wstring widen(const char *str); +CLI11_INLINE std::wstring widen(const char *str, std::size_t size); + +#ifdef CLI11_CPP17 +CLI11_INLINE std::string narrow(std::wstring_view str); +CLI11_INLINE std::wstring widen(std::string_view str); +#endif // CLI11_CPP17 + +#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0 +/// Convert a char-string to a native path correctly. +CLI11_INLINE std::filesystem::path to_path(std::string_view str); +#endif // CLI11_HAS_FILESYSTEM + + + + +namespace detail { + +#if !CLI11_HAS_CODECVT +/// Attempt to set one of the acceptable unicode locales for conversion +CLI11_INLINE void set_unicode_locale() { + static const std::array unicode_locales{{"C.UTF-8", "en_US.UTF-8", ".UTF-8"}}; + + for(const auto &locale_name : unicode_locales) { + if(std::setlocale(LC_ALL, locale_name) != nullptr) { + return; + } + } + throw std::runtime_error("CLI::narrow: could not set locale to C.UTF-8"); +} + +template struct scope_guard_t { + F closure; + + explicit scope_guard_t(F closure_) : closure(closure_) {} + ~scope_guard_t() { closure(); } +}; + +template CLI11_NODISCARD CLI11_INLINE scope_guard_t scope_guard(F &&closure) { + return scope_guard_t{std::forward(closure)}; +} + +#endif // !CLI11_HAS_CODECVT + +CLI11_DIAGNOSTIC_PUSH +CLI11_DIAGNOSTIC_IGNORE_DEPRECATED + +CLI11_INLINE std::string narrow_impl(const wchar_t *str, std::size_t str_size) { +#if CLI11_HAS_CODECVT +#ifdef _WIN32 + return std::wstring_convert>().to_bytes(str, str + str_size); + +#else + return std::wstring_convert>().to_bytes(str, str + str_size); + +#endif // _WIN32 +#else // CLI11_HAS_CODECVT + (void)str_size; + std::mbstate_t state = std::mbstate_t(); + const wchar_t *it = str; + + std::string old_locale = std::setlocale(LC_ALL, nullptr); + auto sg = scope_guard([&] { std::setlocale(LC_ALL, old_locale.c_str()); }); + set_unicode_locale(); + + std::size_t new_size = std::wcsrtombs(nullptr, &it, 0, &state); + if(new_size == static_cast(-1)) { + throw std::runtime_error("CLI::narrow: conversion error in std::wcsrtombs at offset " + + std::to_string(it - str)); + } + std::string result(new_size, '\0'); + std::wcsrtombs(const_cast(result.data()), &str, new_size, &state); + + return result; + +#endif // CLI11_HAS_CODECVT +} + +CLI11_INLINE std::wstring widen_impl(const char *str, std::size_t str_size) { +#if CLI11_HAS_CODECVT +#ifdef _WIN32 + return std::wstring_convert>().from_bytes(str, str + str_size); + +#else + return std::wstring_convert>().from_bytes(str, str + str_size); + +#endif // _WIN32 +#else // CLI11_HAS_CODECVT + (void)str_size; + std::mbstate_t state = std::mbstate_t(); + const char *it = str; + + std::string old_locale = std::setlocale(LC_ALL, nullptr); + auto sg = scope_guard([&] { std::setlocale(LC_ALL, old_locale.c_str()); }); + set_unicode_locale(); + + std::size_t new_size = std::mbsrtowcs(nullptr, &it, 0, &state); + if(new_size == static_cast(-1)) { + throw std::runtime_error("CLI::widen: conversion error in std::mbsrtowcs at offset " + + std::to_string(it - str)); + } + std::wstring result(new_size, L'\0'); + std::mbsrtowcs(const_cast(result.data()), &str, new_size, &state); + + return result; + +#endif // CLI11_HAS_CODECVT +} + +CLI11_DIAGNOSTIC_POP + +} // namespace detail + +CLI11_INLINE std::string narrow(const wchar_t *str, std::size_t str_size) { return detail::narrow_impl(str, str_size); } +CLI11_INLINE std::string narrow(const std::wstring &str) { return detail::narrow_impl(str.data(), str.size()); } +// Flawfinder: ignore +CLI11_INLINE std::string narrow(const wchar_t *str) { return detail::narrow_impl(str, std::wcslen(str)); } + +CLI11_INLINE std::wstring widen(const char *str, std::size_t str_size) { return detail::widen_impl(str, str_size); } +CLI11_INLINE std::wstring widen(const std::string &str) { return detail::widen_impl(str.data(), str.size()); } +// Flawfinder: ignore +CLI11_INLINE std::wstring widen(const char *str) { return detail::widen_impl(str, std::strlen(str)); } + +#ifdef CLI11_CPP17 +CLI11_INLINE std::string narrow(std::wstring_view str) { return detail::narrow_impl(str.data(), str.size()); } +CLI11_INLINE std::wstring widen(std::string_view str) { return detail::widen_impl(str.data(), str.size()); } +#endif // CLI11_CPP17 + +#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0 +CLI11_INLINE std::filesystem::path to_path(std::string_view str) { + return std::filesystem::path{ +#ifdef _WIN32 + widen(str) +#else + str +#endif // _WIN32 + }; +} +#endif // CLI11_HAS_FILESYSTEM + + + + +/// argc as passed in to this executable. +CLI11_INLINE int argc(); + +/// argv as passed in to this executable, converted to utf-8 on Windows. +CLI11_INLINE const char *const *argv(); + + + + +namespace detail { + +#ifdef __APPLE__ +// Copy argc and argv as early as possible to avoid modification +static const std::vector static_args = [] { + static const std::vector static_args_as_strings = [] { + std::vector args_as_strings; + int argc = *_NSGetArgc(); + char **argv = *_NSGetArgv(); + + args_as_strings.reserve(static_cast(argc)); + for(size_t i = 0; i < static_cast(argc); i++) { + args_as_strings.push_back(argv[i]); + } + + return args_as_strings; + }(); + + std::vector static_args_result; + static_args_result.reserve(static_args_as_strings.size()); + + for(const auto &arg : static_args_as_strings) { + static_args_result.push_back(arg.data()); + } + + return static_args_result; +}(); +#endif + +/// Command-line arguments, as passed in to this executable, converted to utf-8 on Windows. +CLI11_INLINE const std::vector &args() { + // This function uses initialization via lambdas extensively to take advantage of the thread safety of static + // variable initialization [stmt.dcl.3] + +#ifdef _WIN32 + static const std::vector static_args = [] { + static const std::vector static_args_as_strings = [] { + // On Windows, take arguments from GetCommandLineW and convert them to utf-8. + std::vector args_as_strings; + int argc = 0; + + auto deleter = [](wchar_t **ptr) { LocalFree(ptr); }; + // NOLINTBEGIN(*-avoid-c-arrays) + auto wargv = + std::unique_ptr(CommandLineToArgvW(GetCommandLineW(), &argc), deleter); + // NOLINTEND(*-avoid-c-arrays) + + if(wargv == nullptr) { + throw std::runtime_error("CommandLineToArgvW failed with code " + std::to_string(GetLastError())); + } + + args_as_strings.reserve(static_cast(argc)); + for(size_t i = 0; i < static_cast(argc); ++i) { + args_as_strings.push_back(narrow(wargv[i])); + } + + return args_as_strings; + }(); + + std::vector static_args_result; + static_args_result.reserve(static_args_as_strings.size()); + + for(const auto &arg : static_args_as_strings) { + static_args_result.push_back(arg.data()); + } + + return static_args_result; + }(); + + return static_args; + +#elif defined(__APPLE__) + + return static_args; + +#else + static const std::vector static_args = [] { + static const std::vector static_cmdline = [] { + // On posix, retrieve arguments from /proc/self/cmdline, separated by null terminators. + std::vector cmdline; + + auto deleter = [](FILE *f) { std::fclose(f); }; + std::unique_ptr fp_unique(std::fopen("/proc/self/cmdline", "r"), deleter); + FILE *fp = fp_unique.get(); + if(!fp) { + throw std::runtime_error("could not open /proc/self/cmdline for reading"); // LCOV_EXCL_LINE + } + + size_t size = 0; + while(std::feof(fp) == 0) { + cmdline.resize(size + 128); + size += std::fread(cmdline.data() + size, 1, 128, fp); + + if(std::ferror(fp) != 0) { + throw std::runtime_error("error during reading /proc/self/cmdline"); // LCOV_EXCL_LINE + } + } + cmdline.resize(size); + + return cmdline; + }(); + + std::size_t argc = static_cast(std::count(static_cmdline.begin(), static_cmdline.end(), '\0')); + std::vector static_args_result; + static_args_result.reserve(argc); + + for(auto it = static_cmdline.begin(); it != static_cmdline.end(); + it = std::find(it, static_cmdline.end(), '\0') + 1) { + static_args_result.push_back(static_cmdline.data() + (it - static_cmdline.begin())); + } + + return static_args_result; + }(); + + return static_args; +#endif +} + +} // namespace detail + +CLI11_INLINE const char *const *argv() { return detail::args().data(); } +CLI11_INLINE int argc() { return static_cast(detail::args().size()); } + + + + +/// Include the items in this namespace to get free conversion of enums to/from streams. +/// (This is available inside CLI as well, so CLI11 will use this without a using statement). +namespace enums { + +/// output streaming for enumerations +template ::value>::type> +std::ostream &operator<<(std::ostream &in, const T &item) { + // make sure this is out of the detail namespace otherwise it won't be found when needed + return in << static_cast::type>(item); +} + +} // namespace enums + +/// Export to CLI namespace +using enums::operator<<; + +namespace detail { +/// a constant defining an expected max vector size defined to be a big number that could be multiplied by 4 and not +/// produce overflow for some expected uses +constexpr int expected_max_vector_size{1 << 29}; +// Based on http://stackoverflow.com/questions/236129/split-a-string-in-c +/// Split a string by a delim +CLI11_INLINE std::vector split(const std::string &s, char delim); + +/// Simple function to join a string +template std::string join(const T &v, std::string delim = ",") { + std::ostringstream s; + auto beg = std::begin(v); + auto end = std::end(v); + if(beg != end) + s << *beg++; + while(beg != end) { + s << delim << *beg++; + } + return s.str(); +} + +/// Simple function to join a string from processed elements +template ::value>::type> +std::string join(const T &v, Callable func, std::string delim = ",") { + std::ostringstream s; + auto beg = std::begin(v); + auto end = std::end(v); + auto loc = s.tellp(); + while(beg != end) { + auto nloc = s.tellp(); + if(nloc > loc) { + s << delim; + loc = nloc; + } + s << func(*beg++); + } + return s.str(); +} + +/// Join a string in reverse order +template std::string rjoin(const T &v, std::string delim = ",") { + std::ostringstream s; + for(std::size_t start = 0; start < v.size(); start++) { + if(start > 0) + s << delim; + s << v[v.size() - start - 1]; + } + return s.str(); +} + +// Based roughly on http://stackoverflow.com/questions/25829143/c-trim-whitespace-from-a-string + +/// Trim whitespace from left of string +CLI11_INLINE std::string <rim(std::string &str); + +/// Trim anything from left of string +CLI11_INLINE std::string <rim(std::string &str, const std::string &filter); + +/// Trim whitespace from right of string +CLI11_INLINE std::string &rtrim(std::string &str); + +/// Trim anything from right of string +CLI11_INLINE std::string &rtrim(std::string &str, const std::string &filter); + +/// Trim whitespace from string +inline std::string &trim(std::string &str) { return ltrim(rtrim(str)); } + +/// Trim anything from string +inline std::string &trim(std::string &str, const std::string filter) { return ltrim(rtrim(str, filter), filter); } + +/// Make a copy of the string and then trim it +inline std::string trim_copy(const std::string &str) { + std::string s = str; + return trim(s); +} + +/// remove quotes at the front and back of a string either '"' or '\'' +CLI11_INLINE std::string &remove_quotes(std::string &str); + +/// Add a leader to the beginning of all new lines (nothing is added +/// at the start of the first line). `"; "` would be for ini files +/// +/// Can't use Regex, or this would be a subs. +CLI11_INLINE std::string fix_newlines(const std::string &leader, std::string input); + +/// Make a copy of the string and then trim it, any filter string can be used (any char in string is filtered) +inline std::string trim_copy(const std::string &str, const std::string &filter) { + std::string s = str; + return trim(s, filter); +} +/// Print a two part "help" string +CLI11_INLINE std::ostream & +format_help(std::ostream &out, std::string name, const std::string &description, std::size_t wid); + +/// Print subcommand aliases +CLI11_INLINE std::ostream &format_aliases(std::ostream &out, const std::vector &aliases, std::size_t wid); + +/// Verify the first character of an option +/// - is a trigger character, ! has special meaning and new lines would just be annoying to deal with +template bool valid_first_char(T c) { return ((c != '-') && (c != '!') && (c != ' ') && c != '\n'); } + +/// Verify following characters of an option +template bool valid_later_char(T c) { + // = and : are value separators, { has special meaning for option defaults, + // and \n would just be annoying to deal with in many places allowing space here has too much potential for + // inadvertent entry errors and bugs + return ((c != '=') && (c != ':') && (c != '{') && (c != ' ') && c != '\n'); +} + +/// Verify an option/subcommand name +CLI11_INLINE bool valid_name_string(const std::string &str); + +/// Verify an app name +inline bool valid_alias_name_string(const std::string &str) { + static const std::string badChars(std::string("\n") + '\0'); + return (str.find_first_of(badChars) == std::string::npos); +} + +/// check if a string is a container segment separator (empty or "%%") +inline bool is_separator(const std::string &str) { + static const std::string sep("%%"); + return (str.empty() || str == sep); +} + +/// Verify that str consists of letters only +inline bool isalpha(const std::string &str) { + return std::all_of(str.begin(), str.end(), [](char c) { return std::isalpha(c, std::locale()); }); +} + +/// Return a lower case version of a string +inline std::string to_lower(std::string str) { + std::transform(std::begin(str), std::end(str), std::begin(str), [](const std::string::value_type &x) { + return std::tolower(x, std::locale()); + }); + return str; +} + +/// remove underscores from a string +inline std::string remove_underscore(std::string str) { + str.erase(std::remove(std::begin(str), std::end(str), '_'), std::end(str)); + return str; +} + +/// Find and replace a substring with another substring +CLI11_INLINE std::string find_and_replace(std::string str, std::string from, std::string to); + +/// check if the flag definitions has possible false flags +inline bool has_default_flag_values(const std::string &flags) { + return (flags.find_first_of("{!") != std::string::npos); +} + +CLI11_INLINE void remove_default_flag_values(std::string &flags); + +/// Check if a string is a member of a list of strings and optionally ignore case or ignore underscores +CLI11_INLINE std::ptrdiff_t find_member(std::string name, + const std::vector names, + bool ignore_case = false, + bool ignore_underscore = false); + +/// Find a trigger string and call a modify callable function that takes the current string and starting position of the +/// trigger and returns the position in the string to search for the next trigger string +template inline std::string find_and_modify(std::string str, std::string trigger, Callable modify) { + std::size_t start_pos = 0; + while((start_pos = str.find(trigger, start_pos)) != std::string::npos) { + start_pos = modify(str, start_pos); + } + return str; +} + +/// Split a string '"one two" "three"' into 'one two', 'three' +/// Quote characters can be ` ' or " +CLI11_INLINE std::vector split_up(std::string str, char delimiter = '\0'); + +/// This function detects an equal or colon followed by an escaped quote after an argument +/// then modifies the string to replace the equality with a space. This is needed +/// to allow the split up function to work properly and is intended to be used with the find_and_modify function +/// the return value is the offset+1 which is required by the find_and_modify function. +CLI11_INLINE std::size_t escape_detect(std::string &str, std::size_t offset); + +/// Add quotes if the string contains spaces +CLI11_INLINE std::string &add_quotes_if_needed(std::string &str); + +/// get the value of an environmental variable or empty string if empty +CLI11_INLINE std::string get_environment_value(const std::string &env_name); +} // namespace detail + + + + +namespace detail { +CLI11_INLINE std::vector split(const std::string &s, char delim) { + std::vector elems; + // Check to see if empty string, give consistent result + if(s.empty()) { + elems.emplace_back(); + } else { + std::stringstream ss; + ss.str(s); + std::string item; + while(std::getline(ss, item, delim)) { + elems.push_back(item); + } + } + return elems; +} + +CLI11_INLINE std::string <rim(std::string &str) { + auto it = std::find_if(str.begin(), str.end(), [](char ch) { return !std::isspace(ch, std::locale()); }); + str.erase(str.begin(), it); + return str; +} + +CLI11_INLINE std::string <rim(std::string &str, const std::string &filter) { + auto it = std::find_if(str.begin(), str.end(), [&filter](char ch) { return filter.find(ch) == std::string::npos; }); + str.erase(str.begin(), it); + return str; +} + +CLI11_INLINE std::string &rtrim(std::string &str) { + auto it = std::find_if(str.rbegin(), str.rend(), [](char ch) { return !std::isspace(ch, std::locale()); }); + str.erase(it.base(), str.end()); + return str; +} + +CLI11_INLINE std::string &rtrim(std::string &str, const std::string &filter) { + auto it = + std::find_if(str.rbegin(), str.rend(), [&filter](char ch) { return filter.find(ch) == std::string::npos; }); + str.erase(it.base(), str.end()); + return str; +} + +CLI11_INLINE std::string &remove_quotes(std::string &str) { + if(str.length() > 1 && (str.front() == '"' || str.front() == '\'')) { + if(str.front() == str.back()) { + str.pop_back(); + str.erase(str.begin(), str.begin() + 1); + } + } + return str; +} + +CLI11_INLINE std::string fix_newlines(const std::string &leader, std::string input) { + std::string::size_type n = 0; + while(n != std::string::npos && n < input.size()) { + n = input.find('\n', n); + if(n != std::string::npos) { + input = input.substr(0, n + 1) + leader + input.substr(n + 1); + n += leader.size(); + } + } + return input; +} + +CLI11_INLINE std::ostream & +format_help(std::ostream &out, std::string name, const std::string &description, std::size_t wid) { + name = " " + name; + out << std::setw(static_cast(wid)) << std::left << name; + if(!description.empty()) { + if(name.length() >= wid) + out << "\n" << std::setw(static_cast(wid)) << ""; + for(const char c : description) { + out.put(c); + if(c == '\n') { + out << std::setw(static_cast(wid)) << ""; + } + } + } + out << "\n"; + return out; +} + +CLI11_INLINE std::ostream &format_aliases(std::ostream &out, const std::vector &aliases, std::size_t wid) { + if(!aliases.empty()) { + out << std::setw(static_cast(wid)) << " aliases: "; + bool front = true; + for(const auto &alias : aliases) { + if(!front) { + out << ", "; + } else { + front = false; + } + out << detail::fix_newlines(" ", alias); + } + out << "\n"; + } + return out; +} + +CLI11_INLINE bool valid_name_string(const std::string &str) { + if(str.empty() || !valid_first_char(str[0])) { + return false; + } + auto e = str.end(); + for(auto c = str.begin() + 1; c != e; ++c) + if(!valid_later_char(*c)) + return false; + return true; +} + +CLI11_INLINE std::string find_and_replace(std::string str, std::string from, std::string to) { + + std::size_t start_pos = 0; + + while((start_pos = str.find(from, start_pos)) != std::string::npos) { + str.replace(start_pos, from.length(), to); + start_pos += to.length(); + } + + return str; +} + +CLI11_INLINE void remove_default_flag_values(std::string &flags) { + auto loc = flags.find_first_of('{', 2); + while(loc != std::string::npos) { + auto finish = flags.find_first_of("},", loc + 1); + if((finish != std::string::npos) && (flags[finish] == '}')) { + flags.erase(flags.begin() + static_cast(loc), + flags.begin() + static_cast(finish) + 1); + } + loc = flags.find_first_of('{', loc + 1); + } + flags.erase(std::remove(flags.begin(), flags.end(), '!'), flags.end()); +} + +CLI11_INLINE std::ptrdiff_t +find_member(std::string name, const std::vector names, bool ignore_case, bool ignore_underscore) { + auto it = std::end(names); + if(ignore_case) { + if(ignore_underscore) { + name = detail::to_lower(detail::remove_underscore(name)); + it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) { + return detail::to_lower(detail::remove_underscore(local_name)) == name; + }); + } else { + name = detail::to_lower(name); + it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) { + return detail::to_lower(local_name) == name; + }); + } + + } else if(ignore_underscore) { + name = detail::remove_underscore(name); + it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) { + return detail::remove_underscore(local_name) == name; + }); + } else { + it = std::find(std::begin(names), std::end(names), name); + } + + return (it != std::end(names)) ? (it - std::begin(names)) : (-1); +} + +CLI11_INLINE std::vector split_up(std::string str, char delimiter) { + + const std::string delims("\'\"`"); + auto find_ws = [delimiter](char ch) { + return (delimiter == '\0') ? std::isspace(ch, std::locale()) : (ch == delimiter); + }; + trim(str); + + std::vector output; + bool embeddedQuote = false; + char keyChar = ' '; + while(!str.empty()) { + if(delims.find_first_of(str[0]) != std::string::npos) { + keyChar = str[0]; + auto end = str.find_first_of(keyChar, 1); + while((end != std::string::npos) && (str[end - 1] == '\\')) { // deal with escaped quotes + end = str.find_first_of(keyChar, end + 1); + embeddedQuote = true; + } + if(end != std::string::npos) { + output.push_back(str.substr(1, end - 1)); + if(end + 2 < str.size()) { + str = str.substr(end + 2); + } else { + str.clear(); + } + + } else { + output.push_back(str.substr(1)); + str = ""; + } + } else { + auto it = std::find_if(std::begin(str), std::end(str), find_ws); + if(it != std::end(str)) { + std::string value = std::string(str.begin(), it); + output.push_back(value); + str = std::string(it + 1, str.end()); + } else { + output.push_back(str); + str = ""; + } + } + // transform any embedded quotes into the regular character + if(embeddedQuote) { + output.back() = find_and_replace(output.back(), std::string("\\") + keyChar, std::string(1, keyChar)); + embeddedQuote = false; + } + trim(str); + } + return output; +} + +CLI11_INLINE std::size_t escape_detect(std::string &str, std::size_t offset) { + auto next = str[offset + 1]; + if((next == '\"') || (next == '\'') || (next == '`')) { + auto astart = str.find_last_of("-/ \"\'`", offset - 1); + if(astart != std::string::npos) { + if(str[astart] == ((str[offset] == '=') ? '-' : '/')) + str[offset] = ' '; // interpret this as a space so the split_up works properly + } + } + return offset + 1; +} + +CLI11_INLINE std::string &add_quotes_if_needed(std::string &str) { + if((str.front() != '"' && str.front() != '\'') || str.front() != str.back()) { + char quote = str.find('"') < str.find('\'') ? '\'' : '"'; + if(str.find(' ') != std::string::npos) { + str.insert(0, 1, quote); + str.append(1, quote); + } + } + return str; +} + +std::string get_environment_value(const std::string &env_name) { + char *buffer = nullptr; + std::string ename_string; + +#ifdef _MSC_VER + // Windows version + std::size_t sz = 0; + if(_dupenv_s(&buffer, &sz, env_name.c_str()) == 0 && buffer != nullptr) { + ename_string = std::string(buffer); + free(buffer); + } +#else + // This also works on Windows, but gives a warning + buffer = std::getenv(env_name.c_str()); + if(buffer != nullptr) { + ename_string = std::string(buffer); + } +#endif + return ename_string; +} + +} // namespace detail + + + +// Use one of these on all error classes. +// These are temporary and are undef'd at the end of this file. +#define CLI11_ERROR_DEF(parent, name) \ + protected: \ + name(std::string ename, std::string msg, int exit_code) : parent(std::move(ename), std::move(msg), exit_code) {} \ + name(std::string ename, std::string msg, ExitCodes exit_code) \ + : parent(std::move(ename), std::move(msg), exit_code) {} \ + \ + public: \ + name(std::string msg, ExitCodes exit_code) : parent(#name, std::move(msg), exit_code) {} \ + name(std::string msg, int exit_code) : parent(#name, std::move(msg), exit_code) {} + +// This is added after the one above if a class is used directly and builds its own message +#define CLI11_ERROR_SIMPLE(name) \ + explicit name(std::string msg) : name(#name, msg, ExitCodes::name) {} + +/// These codes are part of every error in CLI. They can be obtained from e using e.exit_code or as a quick shortcut, +/// int values from e.get_error_code(). +enum class ExitCodes { + Success = 0, + IncorrectConstruction = 100, + BadNameString, + OptionAlreadyAdded, + FileError, + ConversionError, + ValidationError, + RequiredError, + RequiresError, + ExcludesError, + ExtrasError, + ConfigError, + InvalidError, + HorribleError, + OptionNotFound, + ArgumentMismatch, + BaseClass = 127 +}; + +// Error definitions + +/// @defgroup error_group Errors +/// @brief Errors thrown by CLI11 +/// +/// These are the errors that can be thrown. Some of them, like CLI::Success, are not really errors. +/// @{ + +/// All errors derive from this one +class Error : public std::runtime_error { + int actual_exit_code; + std::string error_name{"Error"}; + + public: + CLI11_NODISCARD int get_exit_code() const { return actual_exit_code; } + + CLI11_NODISCARD std::string get_name() const { return error_name; } + + Error(std::string name, std::string msg, int exit_code = static_cast(ExitCodes::BaseClass)) + : runtime_error(msg), actual_exit_code(exit_code), error_name(std::move(name)) {} + + Error(std::string name, std::string msg, ExitCodes exit_code) : Error(name, msg, static_cast(exit_code)) {} +}; + +// Note: Using Error::Error constructors does not work on GCC 4.7 + +/// Construction errors (not in parsing) +class ConstructionError : public Error { + CLI11_ERROR_DEF(Error, ConstructionError) +}; + +/// Thrown when an option is set to conflicting values (non-vector and multi args, for example) +class IncorrectConstruction : public ConstructionError { + CLI11_ERROR_DEF(ConstructionError, IncorrectConstruction) + CLI11_ERROR_SIMPLE(IncorrectConstruction) + static IncorrectConstruction PositionalFlag(std::string name) { + return IncorrectConstruction(name + ": Flags cannot be positional"); + } + static IncorrectConstruction Set0Opt(std::string name) { + return IncorrectConstruction(name + ": Cannot set 0 expected, use a flag instead"); + } + static IncorrectConstruction SetFlag(std::string name) { + return IncorrectConstruction(name + ": Cannot set an expected number for flags"); + } + static IncorrectConstruction ChangeNotVector(std::string name) { + return IncorrectConstruction(name + ": You can only change the expected arguments for vectors"); + } + static IncorrectConstruction AfterMultiOpt(std::string name) { + return IncorrectConstruction( + name + ": You can't change expected arguments after you've changed the multi option policy!"); + } + static IncorrectConstruction MissingOption(std::string name) { + return IncorrectConstruction("Option " + name + " is not defined"); + } + static IncorrectConstruction MultiOptionPolicy(std::string name) { + return IncorrectConstruction(name + ": multi_option_policy only works for flags and exact value options"); + } +}; + +/// Thrown on construction of a bad name +class BadNameString : public ConstructionError { + CLI11_ERROR_DEF(ConstructionError, BadNameString) + CLI11_ERROR_SIMPLE(BadNameString) + static BadNameString OneCharName(std::string name) { return BadNameString("Invalid one char name: " + name); } + static BadNameString MissingDash(std::string name) { + return BadNameString("Long names strings require 2 dashes " + name); + } + static BadNameString BadLongName(std::string name) { return BadNameString("Bad long name: " + name); } + static BadNameString DashesOnly(std::string name) { + return BadNameString("Must have a name, not just dashes: " + name); + } + static BadNameString MultiPositionalNames(std::string name) { + return BadNameString("Only one positional name allowed, remove: " + name); + } +}; + +/// Thrown when an option already exists +class OptionAlreadyAdded : public ConstructionError { + CLI11_ERROR_DEF(ConstructionError, OptionAlreadyAdded) + explicit OptionAlreadyAdded(std::string name) + : OptionAlreadyAdded(name + " is already added", ExitCodes::OptionAlreadyAdded) {} + static OptionAlreadyAdded Requires(std::string name, std::string other) { + return {name + " requires " + other, ExitCodes::OptionAlreadyAdded}; + } + static OptionAlreadyAdded Excludes(std::string name, std::string other) { + return {name + " excludes " + other, ExitCodes::OptionAlreadyAdded}; + } +}; + +// Parsing errors + +/// Anything that can error in Parse +class ParseError : public Error { + CLI11_ERROR_DEF(Error, ParseError) +}; + +// Not really "errors" + +/// This is a successful completion on parsing, supposed to exit +class Success : public ParseError { + CLI11_ERROR_DEF(ParseError, Success) + Success() : Success("Successfully completed, should be caught and quit", ExitCodes::Success) {} +}; + +/// -h or --help on command line +class CallForHelp : public Success { + CLI11_ERROR_DEF(Success, CallForHelp) + CallForHelp() : CallForHelp("This should be caught in your main function, see examples", ExitCodes::Success) {} +}; + +/// Usually something like --help-all on command line +class CallForAllHelp : public Success { + CLI11_ERROR_DEF(Success, CallForAllHelp) + CallForAllHelp() + : CallForAllHelp("This should be caught in your main function, see examples", ExitCodes::Success) {} +}; + +/// -v or --version on command line +class CallForVersion : public Success { + CLI11_ERROR_DEF(Success, CallForVersion) + CallForVersion() + : CallForVersion("This should be caught in your main function, see examples", ExitCodes::Success) {} +}; + +/// Does not output a diagnostic in CLI11_PARSE, but allows main() to return with a specific error code. +class RuntimeError : public ParseError { + CLI11_ERROR_DEF(ParseError, RuntimeError) + explicit RuntimeError(int exit_code = 1) : RuntimeError("Runtime error", exit_code) {} +}; + +/// Thrown when parsing an INI file and it is missing +class FileError : public ParseError { + CLI11_ERROR_DEF(ParseError, FileError) + CLI11_ERROR_SIMPLE(FileError) + static FileError Missing(std::string name) { return FileError(name + " was not readable (missing?)"); } +}; + +/// Thrown when conversion call back fails, such as when an int fails to coerce to a string +class ConversionError : public ParseError { + CLI11_ERROR_DEF(ParseError, ConversionError) + CLI11_ERROR_SIMPLE(ConversionError) + ConversionError(std::string member, std::string name) + : ConversionError("The value " + member + " is not an allowed value for " + name) {} + ConversionError(std::string name, std::vector results) + : ConversionError("Could not convert: " + name + " = " + detail::join(results)) {} + static ConversionError TooManyInputsFlag(std::string name) { + return ConversionError(name + ": too many inputs for a flag"); + } + static ConversionError TrueFalse(std::string name) { + return ConversionError(name + ": Should be true/false or a number"); + } +}; + +/// Thrown when validation of results fails +class ValidationError : public ParseError { + CLI11_ERROR_DEF(ParseError, ValidationError) + CLI11_ERROR_SIMPLE(ValidationError) + explicit ValidationError(std::string name, std::string msg) : ValidationError(name + ": " + msg) {} +}; + +/// Thrown when a required option is missing +class RequiredError : public ParseError { + CLI11_ERROR_DEF(ParseError, RequiredError) + explicit RequiredError(std::string name) : RequiredError(name + " is required", ExitCodes::RequiredError) {} + static RequiredError Subcommand(std::size_t min_subcom) { + if(min_subcom == 1) { + return RequiredError("A subcommand"); + } + return {"Requires at least " + std::to_string(min_subcom) + " subcommands", ExitCodes::RequiredError}; + } + static RequiredError + Option(std::size_t min_option, std::size_t max_option, std::size_t used, const std::string &option_list) { + if((min_option == 1) && (max_option == 1) && (used == 0)) + return RequiredError("Exactly 1 option from [" + option_list + "]"); + if((min_option == 1) && (max_option == 1) && (used > 1)) { + return {"Exactly 1 option from [" + option_list + "] is required and " + std::to_string(used) + + " were given", + ExitCodes::RequiredError}; + } + if((min_option == 1) && (used == 0)) + return RequiredError("At least 1 option from [" + option_list + "]"); + if(used < min_option) { + return {"Requires at least " + std::to_string(min_option) + " options used and only " + + std::to_string(used) + "were given from [" + option_list + "]", + ExitCodes::RequiredError}; + } + if(max_option == 1) + return {"Requires at most 1 options be given from [" + option_list + "]", ExitCodes::RequiredError}; + + return {"Requires at most " + std::to_string(max_option) + " options be used and " + std::to_string(used) + + "were given from [" + option_list + "]", + ExitCodes::RequiredError}; + } +}; + +/// Thrown when the wrong number of arguments has been received +class ArgumentMismatch : public ParseError { + CLI11_ERROR_DEF(ParseError, ArgumentMismatch) + CLI11_ERROR_SIMPLE(ArgumentMismatch) + ArgumentMismatch(std::string name, int expected, std::size_t received) + : ArgumentMismatch(expected > 0 ? ("Expected exactly " + std::to_string(expected) + " arguments to " + name + + ", got " + std::to_string(received)) + : ("Expected at least " + std::to_string(-expected) + " arguments to " + name + + ", got " + std::to_string(received)), + ExitCodes::ArgumentMismatch) {} + + static ArgumentMismatch AtLeast(std::string name, int num, std::size_t received) { + return ArgumentMismatch(name + ": At least " + std::to_string(num) + " required but received " + + std::to_string(received)); + } + static ArgumentMismatch AtMost(std::string name, int num, std::size_t received) { + return ArgumentMismatch(name + ": At Most " + std::to_string(num) + " required but received " + + std::to_string(received)); + } + static ArgumentMismatch TypedAtLeast(std::string name, int num, std::string type) { + return ArgumentMismatch(name + ": " + std::to_string(num) + " required " + type + " missing"); + } + static ArgumentMismatch FlagOverride(std::string name) { + return ArgumentMismatch(name + " was given a disallowed flag override"); + } + static ArgumentMismatch PartialType(std::string name, int num, std::string type) { + return ArgumentMismatch(name + ": " + type + " only partially specified: " + std::to_string(num) + + " required for each element"); + } +}; + +/// Thrown when a requires option is missing +class RequiresError : public ParseError { + CLI11_ERROR_DEF(ParseError, RequiresError) + RequiresError(std::string curname, std::string subname) + : RequiresError(curname + " requires " + subname, ExitCodes::RequiresError) {} +}; + +/// Thrown when an excludes option is present +class ExcludesError : public ParseError { + CLI11_ERROR_DEF(ParseError, ExcludesError) + ExcludesError(std::string curname, std::string subname) + : ExcludesError(curname + " excludes " + subname, ExitCodes::ExcludesError) {} +}; + +/// Thrown when too many positionals or options are found +class ExtrasError : public ParseError { + CLI11_ERROR_DEF(ParseError, ExtrasError) + explicit ExtrasError(std::vector args) + : ExtrasError((args.size() > 1 ? "The following arguments were not expected: " + : "The following argument was not expected: ") + + detail::rjoin(args, " "), + ExitCodes::ExtrasError) {} + ExtrasError(const std::string &name, std::vector args) + : ExtrasError(name, + (args.size() > 1 ? "The following arguments were not expected: " + : "The following argument was not expected: ") + + detail::rjoin(args, " "), + ExitCodes::ExtrasError) {} +}; + +/// Thrown when extra values are found in an INI file +class ConfigError : public ParseError { + CLI11_ERROR_DEF(ParseError, ConfigError) + CLI11_ERROR_SIMPLE(ConfigError) + static ConfigError Extras(std::string item) { return ConfigError("INI was not able to parse " + item); } + static ConfigError NotConfigurable(std::string item) { + return ConfigError(item + ": This option is not allowed in a configuration file"); + } +}; + +/// Thrown when validation fails before parsing +class InvalidError : public ParseError { + CLI11_ERROR_DEF(ParseError, InvalidError) + explicit InvalidError(std::string name) + : InvalidError(name + ": Too many positional arguments with unlimited expected args", ExitCodes::InvalidError) { + } +}; + +/// This is just a safety check to verify selection and parsing match - you should not ever see it +/// Strings are directly added to this error, but again, it should never be seen. +class HorribleError : public ParseError { + CLI11_ERROR_DEF(ParseError, HorribleError) + CLI11_ERROR_SIMPLE(HorribleError) +}; + +// After parsing + +/// Thrown when counting a non-existent option +class OptionNotFound : public Error { + CLI11_ERROR_DEF(Error, OptionNotFound) + explicit OptionNotFound(std::string name) : OptionNotFound(name + " not found", ExitCodes::OptionNotFound) {} +}; + +#undef CLI11_ERROR_DEF +#undef CLI11_ERROR_SIMPLE + +/// @} + + + + +// Type tools + +// Utilities for type enabling +namespace detail { +// Based generally on https://rmf.io/cxx11/almost-static-if +/// Simple empty scoped class +enum class enabler {}; + +/// An instance to use in EnableIf +constexpr enabler dummy = {}; +} // namespace detail + +/// A copy of enable_if_t from C++14, compatible with C++11. +/// +/// We could check to see if C++14 is being used, but it does not hurt to redefine this +/// (even Google does this: https://github.com/google/skia/blob/main/include/private/SkTLogic.h) +/// It is not in the std namespace anyway, so no harm done. +template using enable_if_t = typename std::enable_if::type; + +/// A copy of std::void_t from C++17 (helper for C++11 and C++14) +template struct make_void { + using type = void; +}; + +/// A copy of std::void_t from C++17 - same reasoning as enable_if_t, it does not hurt to redefine +template using void_t = typename make_void::type; + +/// A copy of std::conditional_t from C++14 - same reasoning as enable_if_t, it does not hurt to redefine +template using conditional_t = typename std::conditional::type; + +/// Check to see if something is bool (fail check by default) +template struct is_bool : std::false_type {}; + +/// Check to see if something is bool (true if actually a bool) +template <> struct is_bool : std::true_type {}; + +/// Check to see if something is a shared pointer +template struct is_shared_ptr : std::false_type {}; + +/// Check to see if something is a shared pointer (True if really a shared pointer) +template struct is_shared_ptr> : std::true_type {}; + +/// Check to see if something is a shared pointer (True if really a shared pointer) +template struct is_shared_ptr> : std::true_type {}; + +/// Check to see if something is copyable pointer +template struct is_copyable_ptr { + static bool const value = is_shared_ptr::value || std::is_pointer::value; +}; + +/// This can be specialized to override the type deduction for IsMember. +template struct IsMemberType { + using type = T; +}; + +/// The main custom type needed here is const char * should be a string. +template <> struct IsMemberType { + using type = std::string; +}; + +namespace detail { + +// These are utilities for IsMember and other transforming objects + +/// Handy helper to access the element_type generically. This is not part of is_copyable_ptr because it requires that +/// pointer_traits be valid. + +/// not a pointer +template struct element_type { + using type = T; +}; + +template struct element_type::value>::type> { + using type = typename std::pointer_traits::element_type; +}; + +/// Combination of the element type and value type - remove pointer (including smart pointers) and get the value_type of +/// the container +template struct element_value_type { + using type = typename element_type::type::value_type; +}; + +/// Adaptor for set-like structure: This just wraps a normal container in a few utilities that do almost nothing. +template struct pair_adaptor : std::false_type { + using value_type = typename T::value_type; + using first_type = typename std::remove_const::type; + using second_type = typename std::remove_const::type; + + /// Get the first value (really just the underlying value) + template static auto first(Q &&pair_value) -> decltype(std::forward(pair_value)) { + return std::forward(pair_value); + } + /// Get the second value (really just the underlying value) + template static auto second(Q &&pair_value) -> decltype(std::forward(pair_value)) { + return std::forward(pair_value); + } +}; + +/// Adaptor for map-like structure (true version, must have key_type and mapped_type). +/// This wraps a mapped container in a few utilities access it in a general way. +template +struct pair_adaptor< + T, + conditional_t, void>> + : std::true_type { + using value_type = typename T::value_type; + using first_type = typename std::remove_const::type; + using second_type = typename std::remove_const::type; + + /// Get the first value (really just the underlying value) + template static auto first(Q &&pair_value) -> decltype(std::get<0>(std::forward(pair_value))) { + return std::get<0>(std::forward(pair_value)); + } + /// Get the second value (really just the underlying value) + template static auto second(Q &&pair_value) -> decltype(std::get<1>(std::forward(pair_value))) { + return std::get<1>(std::forward(pair_value)); + } +}; + +// Warning is suppressed due to "bug" in gcc<5.0 and gcc 7.0 with c++17 enabled that generates a Wnarrowing warning +// in the unevaluated context even if the function that was using this wasn't used. The standard says narrowing in +// brace initialization shouldn't be allowed but for backwards compatibility gcc allows it in some contexts. It is a +// little fuzzy what happens in template constructs and I think that was something GCC took a little while to work out. +// But regardless some versions of gcc generate a warning when they shouldn't from the following code so that should be +// suppressed +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnarrowing" +#endif +// check for constructibility from a specific type and copy assignable used in the parse detection +template class is_direct_constructible { + template + static auto test(int, std::true_type) -> decltype( +// NVCC warns about narrowing conversions here +#ifdef __CUDACC__ +#ifdef __NVCC_DIAG_PRAGMA_SUPPORT__ +#pragma nv_diag_suppress 2361 +#else +#pragma diag_suppress 2361 +#endif +#endif + TT{std::declval()} +#ifdef __CUDACC__ +#ifdef __NVCC_DIAG_PRAGMA_SUPPORT__ +#pragma nv_diag_default 2361 +#else +#pragma diag_default 2361 +#endif +#endif + , + std::is_move_assignable()); + + template static auto test(int, std::false_type) -> std::false_type; + + template static auto test(...) -> std::false_type; + + public: + static constexpr bool value = decltype(test(0, typename std::is_constructible::type()))::value; +}; +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +// Check for output streamability +// Based on https://stackoverflow.com/questions/22758291/how-can-i-detect-if-a-type-can-be-streamed-to-an-stdostream + +template class is_ostreamable { + template + static auto test(int) -> decltype(std::declval() << std::declval(), std::true_type()); + + template static auto test(...) -> std::false_type; + + public: + static constexpr bool value = decltype(test(0))::value; +}; + +/// Check for input streamability +template class is_istreamable { + template + static auto test(int) -> decltype(std::declval() >> std::declval(), std::true_type()); + + template static auto test(...) -> std::false_type; + + public: + static constexpr bool value = decltype(test(0))::value; +}; + +/// Check for complex +template class is_complex { + template + static auto test(int) -> decltype(std::declval().real(), std::declval().imag(), std::true_type()); + + template static auto test(...) -> std::false_type; + + public: + static constexpr bool value = decltype(test(0))::value; +}; + +/// Templated operation to get a value from a stream +template ::value, detail::enabler> = detail::dummy> +bool from_stream(const std::string &istring, T &obj) { + std::istringstream is; + is.str(istring); + is >> obj; + return !is.fail() && !is.rdbuf()->in_avail(); +} + +template ::value, detail::enabler> = detail::dummy> +bool from_stream(const std::string & /*istring*/, T & /*obj*/) { + return false; +} + +// check to see if an object is a mutable container (fail by default) +template struct is_mutable_container : std::false_type {}; + +/// type trait to test if a type is a mutable container meaning it has a value_type, it has an iterator, a clear, and +/// end methods and an insert function. And for our purposes we exclude std::string and types that can be constructed +/// from a std::string +template +struct is_mutable_container< + T, + conditional_t().end()), + decltype(std::declval().clear()), + decltype(std::declval().insert(std::declval().end())>(), + std::declval()))>, + void>> : public conditional_t::value || + std::is_constructible::value, + std::false_type, + std::true_type> {}; + +// check to see if an object is a mutable container (fail by default) +template struct is_readable_container : std::false_type {}; + +/// type trait to test if a type is a container meaning it has a value_type, it has an iterator, a clear, and an end +/// methods and an insert function. And for our purposes we exclude std::string and types that can be constructed from +/// a std::string +template +struct is_readable_container< + T, + conditional_t().end()), decltype(std::declval().begin())>, void>> + : public std::true_type {}; + +// check to see if an object is a wrapper (fail by default) +template struct is_wrapper : std::false_type {}; + +// check if an object is a wrapper (it has a value_type defined) +template +struct is_wrapper, void>> : public std::true_type {}; + +// Check for tuple like types, as in classes with a tuple_size type trait +template class is_tuple_like { + template + // static auto test(int) + // -> decltype(std::conditional<(std::tuple_size::value > 0), std::true_type, std::false_type>::type()); + static auto test(int) -> decltype(std::tuple_size::type>::value, std::true_type{}); + template static auto test(...) -> std::false_type; + + public: + static constexpr bool value = decltype(test(0))::value; +}; + +/// Convert an object to a string (directly forward if this can become a string) +template ::value, detail::enabler> = detail::dummy> +auto to_string(T &&value) -> decltype(std::forward(value)) { + return std::forward(value); +} + +/// Construct a string from the object +template ::value && !std::is_convertible::value, + detail::enabler> = detail::dummy> +std::string to_string(const T &value) { + return std::string(value); // NOLINT(google-readability-casting) +} + +/// Convert an object to a string (streaming must be supported for that type) +template ::value && !std::is_constructible::value && + is_ostreamable::value, + detail::enabler> = detail::dummy> +std::string to_string(T &&value) { + std::stringstream stream; + stream << value; + return stream.str(); +} + +/// If conversion is not supported, return an empty string (streaming is not supported for that type) +template ::value && !is_ostreamable::value && + !is_readable_container::type>::value, + detail::enabler> = detail::dummy> +std::string to_string(T &&) { + return {}; +} + +/// convert a readable container to a string +template ::value && !is_ostreamable::value && + is_readable_container::value, + detail::enabler> = detail::dummy> +std::string to_string(T &&variable) { + auto cval = variable.begin(); + auto end = variable.end(); + if(cval == end) { + return {"{}"}; + } + std::vector defaults; + while(cval != end) { + defaults.emplace_back(CLI::detail::to_string(*cval)); + ++cval; + } + return {"[" + detail::join(defaults) + "]"}; +} + +/// special template overload +template ::value, detail::enabler> = detail::dummy> +auto checked_to_string(T &&value) -> decltype(to_string(std::forward(value))) { + return to_string(std::forward(value)); +} + +/// special template overload +template ::value, detail::enabler> = detail::dummy> +std::string checked_to_string(T &&) { + return std::string{}; +} +/// get a string as a convertible value for arithmetic types +template ::value, detail::enabler> = detail::dummy> +std::string value_string(const T &value) { + return std::to_string(value); +} +/// get a string as a convertible value for enumerations +template ::value, detail::enabler> = detail::dummy> +std::string value_string(const T &value) { + return std::to_string(static_cast::type>(value)); +} +/// for other types just use the regular to_string function +template ::value && !std::is_arithmetic::value, detail::enabler> = detail::dummy> +auto value_string(const T &value) -> decltype(to_string(value)) { + return to_string(value); +} + +/// template to get the underlying value type if it exists or use a default +template struct wrapped_type { + using type = def; +}; + +/// Type size for regular object types that do not look like a tuple +template struct wrapped_type::value>::type> { + using type = typename T::value_type; +}; + +/// This will only trigger for actual void type +template struct type_count_base { + static const int value{0}; +}; + +/// Type size for regular object types that do not look like a tuple +template +struct type_count_base::value && !is_mutable_container::value && + !std::is_void::value>::type> { + static constexpr int value{1}; +}; + +/// the base tuple size +template +struct type_count_base::value && !is_mutable_container::value>::type> { + static constexpr int value{std::tuple_size::value}; +}; + +/// Type count base for containers is the type_count_base of the individual element +template struct type_count_base::value>::type> { + static constexpr int value{type_count_base::value}; +}; + +/// Set of overloads to get the type size of an object + +/// forward declare the subtype_count structure +template struct subtype_count; + +/// forward declare the subtype_count_min structure +template struct subtype_count_min; + +/// This will only trigger for actual void type +template struct type_count { + static const int value{0}; +}; + +/// Type size for regular object types that do not look like a tuple +template +struct type_count::value && !is_tuple_like::value && !is_complex::value && + !std::is_void::value>::type> { + static constexpr int value{1}; +}; + +/// Type size for complex since it sometimes looks like a wrapper +template struct type_count::value>::type> { + static constexpr int value{2}; +}; + +/// Type size of types that are wrappers,except complex and tuples(which can also be wrappers sometimes) +template struct type_count::value>::type> { + static constexpr int value{subtype_count::value}; +}; + +/// Type size of types that are wrappers,except containers complex and tuples(which can also be wrappers sometimes) +template +struct type_count::value && !is_complex::value && !is_tuple_like::value && + !is_mutable_container::value>::type> { + static constexpr int value{type_count::value}; +}; + +/// 0 if the index > tuple size +template +constexpr typename std::enable_if::value, int>::type tuple_type_size() { + return 0; +} + +/// Recursively generate the tuple type name +template + constexpr typename std::enable_if < I::value, int>::type tuple_type_size() { + return subtype_count::type>::value + tuple_type_size(); +} + +/// Get the type size of the sum of type sizes for all the individual tuple types +template struct type_count::value>::type> { + static constexpr int value{tuple_type_size()}; +}; + +/// definition of subtype count +template struct subtype_count { + static constexpr int value{is_mutable_container::value ? expected_max_vector_size : type_count::value}; +}; + +/// This will only trigger for actual void type +template struct type_count_min { + static const int value{0}; +}; + +/// Type size for regular object types that do not look like a tuple +template +struct type_count_min< + T, + typename std::enable_if::value && !is_tuple_like::value && !is_wrapper::value && + !is_complex::value && !std::is_void::value>::type> { + static constexpr int value{type_count::value}; +}; + +/// Type size for complex since it sometimes looks like a wrapper +template struct type_count_min::value>::type> { + static constexpr int value{1}; +}; + +/// Type size min of types that are wrappers,except complex and tuples(which can also be wrappers sometimes) +template +struct type_count_min< + T, + typename std::enable_if::value && !is_complex::value && !is_tuple_like::value>::type> { + static constexpr int value{subtype_count_min::value}; +}; + +/// 0 if the index > tuple size +template +constexpr typename std::enable_if::value, int>::type tuple_type_size_min() { + return 0; +} + +/// Recursively generate the tuple type name +template + constexpr typename std::enable_if < I::value, int>::type tuple_type_size_min() { + return subtype_count_min::type>::value + tuple_type_size_min(); +} + +/// Get the type size of the sum of type sizes for all the individual tuple types +template struct type_count_min::value>::type> { + static constexpr int value{tuple_type_size_min()}; +}; + +/// definition of subtype count +template struct subtype_count_min { + static constexpr int value{is_mutable_container::value + ? ((type_count::value < expected_max_vector_size) ? type_count::value : 0) + : type_count_min::value}; +}; + +/// This will only trigger for actual void type +template struct expected_count { + static const int value{0}; +}; + +/// For most types the number of expected items is 1 +template +struct expected_count::value && !is_wrapper::value && + !std::is_void::value>::type> { + static constexpr int value{1}; +}; +/// number of expected items in a vector +template struct expected_count::value>::type> { + static constexpr int value{expected_max_vector_size}; +}; + +/// number of expected items in a vector +template +struct expected_count::value && is_wrapper::value>::type> { + static constexpr int value{expected_count::value}; +}; + +// Enumeration of the different supported categorizations of objects +enum class object_category : int { + char_value = 1, + integral_value = 2, + unsigned_integral = 4, + enumeration = 6, + boolean_value = 8, + floating_point = 10, + number_constructible = 12, + double_constructible = 14, + integer_constructible = 16, + // string like types + string_assignable = 23, + string_constructible = 24, + wstring_assignable = 25, + wstring_constructible = 26, + other = 45, + // special wrapper or container types + wrapper_value = 50, + complex_number = 60, + tuple_value = 70, + container_value = 80, + +}; + +/// Set of overloads to classify an object according to type + +/// some type that is not otherwise recognized +template struct classify_object { + static constexpr object_category value{object_category::other}; +}; + +/// Signed integers +template +struct classify_object< + T, + typename std::enable_if::value && !std::is_same::value && std::is_signed::value && + !is_bool::value && !std::is_enum::value>::type> { + static constexpr object_category value{object_category::integral_value}; +}; + +/// Unsigned integers +template +struct classify_object::value && std::is_unsigned::value && + !std::is_same::value && !is_bool::value>::type> { + static constexpr object_category value{object_category::unsigned_integral}; +}; + +/// single character values +template +struct classify_object::value && !std::is_enum::value>::type> { + static constexpr object_category value{object_category::char_value}; +}; + +/// Boolean values +template struct classify_object::value>::type> { + static constexpr object_category value{object_category::boolean_value}; +}; + +/// Floats +template struct classify_object::value>::type> { + static constexpr object_category value{object_category::floating_point}; +}; +#if defined _MSC_VER +// in MSVC wstring should take precedence if available this isn't as useful on other compilers due to the broader use of +// utf-8 encoding +#define WIDE_STRING_CHECK \ + !std::is_assignable::value && !std::is_constructible::value +#define STRING_CHECK true +#else +#define WIDE_STRING_CHECK true +#define STRING_CHECK !std::is_assignable::value && !std::is_constructible::value +#endif + +/// String and similar direct assignment +template +struct classify_object< + T, + typename std::enable_if::value && !std::is_integral::value && WIDE_STRING_CHECK && + std::is_assignable::value>::type> { + static constexpr object_category value{object_category::string_assignable}; +}; + +/// String and similar constructible and copy assignment +template +struct classify_object< + T, + typename std::enable_if::value && !std::is_integral::value && + !std::is_assignable::value && (type_count::value == 1) && + WIDE_STRING_CHECK && std::is_constructible::value>::type> { + static constexpr object_category value{object_category::string_constructible}; +}; + +/// Wide strings +template +struct classify_object::value && !std::is_integral::value && + STRING_CHECK && std::is_assignable::value>::type> { + static constexpr object_category value{object_category::wstring_assignable}; +}; + +template +struct classify_object< + T, + typename std::enable_if::value && !std::is_integral::value && + !std::is_assignable::value && (type_count::value == 1) && + STRING_CHECK && std::is_constructible::value>::type> { + static constexpr object_category value{object_category::wstring_constructible}; +}; + +/// Enumerations +template struct classify_object::value>::type> { + static constexpr object_category value{object_category::enumeration}; +}; + +template struct classify_object::value>::type> { + static constexpr object_category value{object_category::complex_number}; +}; + +/// Handy helper to contain a bunch of checks that rule out many common types (integers, string like, floating point, +/// vectors, and enumerations +template struct uncommon_type { + using type = typename std::conditional< + !std::is_floating_point::value && !std::is_integral::value && + !std::is_assignable::value && !std::is_constructible::value && + !std::is_assignable::value && !std::is_constructible::value && + !is_complex::value && !is_mutable_container::value && !std::is_enum::value, + std::true_type, + std::false_type>::type; + static constexpr bool value = type::value; +}; + +/// wrapper type +template +struct classify_object::value && is_wrapper::value && + !is_tuple_like::value && uncommon_type::value)>::type> { + static constexpr object_category value{object_category::wrapper_value}; +}; + +/// Assignable from double or int +template +struct classify_object::value && type_count::value == 1 && + !is_wrapper::value && is_direct_constructible::value && + is_direct_constructible::value>::type> { + static constexpr object_category value{object_category::number_constructible}; +}; + +/// Assignable from int +template +struct classify_object::value && type_count::value == 1 && + !is_wrapper::value && !is_direct_constructible::value && + is_direct_constructible::value>::type> { + static constexpr object_category value{object_category::integer_constructible}; +}; + +/// Assignable from double +template +struct classify_object::value && type_count::value == 1 && + !is_wrapper::value && is_direct_constructible::value && + !is_direct_constructible::value>::type> { + static constexpr object_category value{object_category::double_constructible}; +}; + +/// Tuple type +template +struct classify_object< + T, + typename std::enable_if::value && + ((type_count::value >= 2 && !is_wrapper::value) || + (uncommon_type::value && !is_direct_constructible::value && + !is_direct_constructible::value) || + (uncommon_type::value && type_count::value >= 2))>::type> { + static constexpr object_category value{object_category::tuple_value}; + // the condition on this class requires it be like a tuple, but on some compilers (like Xcode) tuples can be + // constructed from just the first element so tuples of can be constructed from a string, which + // could lead to issues so there are two variants of the condition, the first isolates things with a type size >=2 + // mainly to get tuples on Xcode with the exception of wrappers, the second is the main one and just separating out + // those cases that are caught by other object classifications +}; + +/// container type +template struct classify_object::value>::type> { + static constexpr object_category value{object_category::container_value}; +}; + +// Type name print + +/// Was going to be based on +/// http://stackoverflow.com/questions/1055452/c-get-name-of-type-in-template +/// But this is cleaner and works better in this case + +template ::value == object_category::char_value, detail::enabler> = detail::dummy> +constexpr const char *type_name() { + return "CHAR"; +} + +template ::value == object_category::integral_value || + classify_object::value == object_category::integer_constructible, + detail::enabler> = detail::dummy> +constexpr const char *type_name() { + return "INT"; +} + +template ::value == object_category::unsigned_integral, detail::enabler> = detail::dummy> +constexpr const char *type_name() { + return "UINT"; +} + +template ::value == object_category::floating_point || + classify_object::value == object_category::number_constructible || + classify_object::value == object_category::double_constructible, + detail::enabler> = detail::dummy> +constexpr const char *type_name() { + return "FLOAT"; +} + +/// Print name for enumeration types +template ::value == object_category::enumeration, detail::enabler> = detail::dummy> +constexpr const char *type_name() { + return "ENUM"; +} + +/// Print name for enumeration types +template ::value == object_category::boolean_value, detail::enabler> = detail::dummy> +constexpr const char *type_name() { + return "BOOLEAN"; +} + +/// Print name for enumeration types +template ::value == object_category::complex_number, detail::enabler> = detail::dummy> +constexpr const char *type_name() { + return "COMPLEX"; +} + +/// Print for all other types +template ::value >= object_category::string_assignable && + classify_object::value <= object_category::other, + detail::enabler> = detail::dummy> +constexpr const char *type_name() { + return "TEXT"; +} +/// typename for tuple value +template ::value == object_category::tuple_value && type_count_base::value >= 2, + detail::enabler> = detail::dummy> +std::string type_name(); // forward declaration + +/// Generate type name for a wrapper or container value +template ::value == object_category::container_value || + classify_object::value == object_category::wrapper_value, + detail::enabler> = detail::dummy> +std::string type_name(); // forward declaration + +/// Print name for single element tuple types +template ::value == object_category::tuple_value && type_count_base::value == 1, + detail::enabler> = detail::dummy> +inline std::string type_name() { + return type_name::type>::type>(); +} + +/// Empty string if the index > tuple size +template +inline typename std::enable_if::value, std::string>::type tuple_name() { + return std::string{}; +} + +/// Recursively generate the tuple type name +template +inline typename std::enable_if<(I < type_count_base::value), std::string>::type tuple_name() { + auto str = std::string{type_name::type>::type>()} + ',' + + tuple_name(); + if(str.back() == ',') + str.pop_back(); + return str; +} + +/// Print type name for tuples with 2 or more elements +template ::value == object_category::tuple_value && type_count_base::value >= 2, + detail::enabler>> +inline std::string type_name() { + auto tname = std::string(1, '[') + tuple_name(); + tname.push_back(']'); + return tname; +} + +/// get the type name for a type that has a value_type member +template ::value == object_category::container_value || + classify_object::value == object_category::wrapper_value, + detail::enabler>> +inline std::string type_name() { + return type_name(); +} + +// Lexical cast + +/// Convert to an unsigned integral +template ::value, detail::enabler> = detail::dummy> +bool integral_conversion(const std::string &input, T &output) noexcept { + if(input.empty() || input.front() == '-') { + return false; + } + char *val = nullptr; + errno = 0; + std::uint64_t output_ll = std::strtoull(input.c_str(), &val, 0); + if(errno == ERANGE) { + return false; + } + output = static_cast(output_ll); + if(val == (input.c_str() + input.size()) && static_cast(output) == output_ll) { + return true; + } + val = nullptr; + std::int64_t output_sll = std::strtoll(input.c_str(), &val, 0); + if(val == (input.c_str() + input.size())) { + output = (output_sll < 0) ? static_cast(0) : static_cast(output_sll); + return (static_cast(output) == output_sll); + } + return false; +} + +/// Convert to a signed integral +template ::value, detail::enabler> = detail::dummy> +bool integral_conversion(const std::string &input, T &output) noexcept { + if(input.empty()) { + return false; + } + char *val = nullptr; + errno = 0; + std::int64_t output_ll = std::strtoll(input.c_str(), &val, 0); + if(errno == ERANGE) { + return false; + } + output = static_cast(output_ll); + if(val == (input.c_str() + input.size()) && static_cast(output) == output_ll) { + return true; + } + if(input == "true") { + // this is to deal with a few oddities with flags and wrapper int types + output = static_cast(1); + return true; + } + return false; +} + +/// Convert a flag into an integer value typically binary flags +inline std::int64_t to_flag_value(std::string val) { + static const std::string trueString("true"); + static const std::string falseString("false"); + if(val == trueString) { + return 1; + } + if(val == falseString) { + return -1; + } + val = detail::to_lower(val); + std::int64_t ret = 0; + if(val.size() == 1) { + if(val[0] >= '1' && val[0] <= '9') { + return (static_cast(val[0]) - '0'); + } + switch(val[0]) { + case '0': + case 'f': + case 'n': + case '-': + ret = -1; + break; + case 't': + case 'y': + case '+': + ret = 1; + break; + default: + throw std::invalid_argument("unrecognized character"); + } + return ret; + } + if(val == trueString || val == "on" || val == "yes" || val == "enable") { + ret = 1; + } else if(val == falseString || val == "off" || val == "no" || val == "disable") { + ret = -1; + } else { + ret = std::stoll(val); + } + return ret; +} + +/// Integer conversion +template ::value == object_category::integral_value || + classify_object::value == object_category::unsigned_integral, + detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + return integral_conversion(input, output); +} + +/// char values +template ::value == object_category::char_value, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + if(input.size() == 1) { + output = static_cast(input[0]); + return true; + } + return integral_conversion(input, output); +} + +/// Boolean values +template ::value == object_category::boolean_value, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + try { + auto out = to_flag_value(input); + output = (out > 0); + return true; + } catch(const std::invalid_argument &) { + return false; + } catch(const std::out_of_range &) { + // if the number is out of the range of a 64 bit value then it is still a number and for this purpose is still + // valid all we care about the sign + output = (input[0] != '-'); + return true; + } +} + +/// Floats +template ::value == object_category::floating_point, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + if(input.empty()) { + return false; + } + char *val = nullptr; + auto output_ld = std::strtold(input.c_str(), &val); + output = static_cast(output_ld); + return val == (input.c_str() + input.size()); +} + +/// complex +template ::value == object_category::complex_number, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + using XC = typename wrapped_type::type; + XC x{0.0}, y{0.0}; + auto str1 = input; + bool worked = false; + auto nloc = str1.find_last_of("+-"); + if(nloc != std::string::npos && nloc > 0) { + worked = lexical_cast(str1.substr(0, nloc), x); + str1 = str1.substr(nloc); + if(str1.back() == 'i' || str1.back() == 'j') + str1.pop_back(); + worked = worked && lexical_cast(str1, y); + } else { + if(str1.back() == 'i' || str1.back() == 'j') { + str1.pop_back(); + worked = lexical_cast(str1, y); + x = XC{0}; + } else { + worked = lexical_cast(str1, x); + y = XC{0}; + } + } + if(worked) { + output = T{x, y}; + return worked; + } + return from_stream(input, output); +} + +/// String and similar direct assignment +template ::value == object_category::string_assignable, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + output = input; + return true; +} + +/// String and similar constructible and copy assignment +template < + typename T, + enable_if_t::value == object_category::string_constructible, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + output = T(input); + return true; +} + +/// Wide strings +template < + typename T, + enable_if_t::value == object_category::wstring_assignable, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + output = widen(input); + return true; +} + +template < + typename T, + enable_if_t::value == object_category::wstring_constructible, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + output = T{widen(input)}; + return true; +} + +/// Enumerations +template ::value == object_category::enumeration, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + typename std::underlying_type::type val; + if(!integral_conversion(input, val)) { + return false; + } + output = static_cast(val); + return true; +} + +/// wrapper types +template ::value == object_category::wrapper_value && + std::is_assignable::value, + detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + typename T::value_type val; + if(lexical_cast(input, val)) { + output = val; + return true; + } + return from_stream(input, output); +} + +template ::value == object_category::wrapper_value && + !std::is_assignable::value && std::is_assignable::value, + detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + typename T::value_type val; + if(lexical_cast(input, val)) { + output = T{val}; + return true; + } + return from_stream(input, output); +} + +/// Assignable from double or int +template < + typename T, + enable_if_t::value == object_category::number_constructible, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + int val = 0; + if(integral_conversion(input, val)) { + output = T(val); + return true; + } + + double dval = 0.0; + if(lexical_cast(input, dval)) { + output = T{dval}; + return true; + } + + return from_stream(input, output); +} + +/// Assignable from int +template < + typename T, + enable_if_t::value == object_category::integer_constructible, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + int val = 0; + if(integral_conversion(input, val)) { + output = T(val); + return true; + } + return from_stream(input, output); +} + +/// Assignable from double +template < + typename T, + enable_if_t::value == object_category::double_constructible, detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + double val = 0.0; + if(lexical_cast(input, val)) { + output = T{val}; + return true; + } + return from_stream(input, output); +} + +/// Non-string convertible from an int +template ::value == object_category::other && std::is_assignable::value, + detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + int val = 0; + if(integral_conversion(input, val)) { +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4800) +#endif + // with Atomic this could produce a warning due to the conversion but if atomic gets here it is an old style + // so will most likely still work + output = val; +#ifdef _MSC_VER +#pragma warning(pop) +#endif + return true; + } + // LCOV_EXCL_START + // This version of cast is only used for odd cases in an older compilers the fail over + // from_stream is tested elsewhere an not relevant for coverage here + return from_stream(input, output); + // LCOV_EXCL_STOP +} + +/// Non-string parsable by a stream +template ::value == object_category::other && !std::is_assignable::value, + detail::enabler> = detail::dummy> +bool lexical_cast(const std::string &input, T &output) { + static_assert(is_istreamable::value, + "option object type must have a lexical cast overload or streaming input operator(>>) defined, if it " + "is convertible from another type use the add_option(...) with XC being the known type"); + return from_stream(input, output); +} + +/// Assign a value through lexical cast operations +/// Strings can be empty so we need to do a little different +template ::value && + (classify_object::value == object_category::string_assignable || + classify_object::value == object_category::string_constructible || + classify_object::value == object_category::wstring_assignable || + classify_object::value == object_category::wstring_constructible), + detail::enabler> = detail::dummy> +bool lexical_assign(const std::string &input, AssignTo &output) { + return lexical_cast(input, output); +} + +/// Assign a value through lexical cast operations +template ::value && std::is_assignable::value && + classify_object::value != object_category::string_assignable && + classify_object::value != object_category::string_constructible && + classify_object::value != object_category::wstring_assignable && + classify_object::value != object_category::wstring_constructible, + detail::enabler> = detail::dummy> +bool lexical_assign(const std::string &input, AssignTo &output) { + if(input.empty()) { + output = AssignTo{}; + return true; + } + + return lexical_cast(input, output); +} + +/// Assign a value through lexical cast operations +template ::value && !std::is_assignable::value && + classify_object::value == object_category::wrapper_value, + detail::enabler> = detail::dummy> +bool lexical_assign(const std::string &input, AssignTo &output) { + if(input.empty()) { + typename AssignTo::value_type emptyVal{}; + output = emptyVal; + return true; + } + return lexical_cast(input, output); +} + +/// Assign a value through lexical cast operations for int compatible values +/// mainly for atomic operations on some compilers +template ::value && !std::is_assignable::value && + classify_object::value != object_category::wrapper_value && + std::is_assignable::value, + detail::enabler> = detail::dummy> +bool lexical_assign(const std::string &input, AssignTo &output) { + if(input.empty()) { + output = 0; + return true; + } + int val{0}; + if(lexical_cast(input, val)) { +#if defined(__clang__) +/* on some older clang compilers */ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wsign-conversion" +#endif + output = val; +#if defined(__clang__) +#pragma clang diagnostic pop +#endif + return true; + } + return false; +} + +/// Assign a value converted from a string in lexical cast to the output value directly +template ::value && std::is_assignable::value, + detail::enabler> = detail::dummy> +bool lexical_assign(const std::string &input, AssignTo &output) { + ConvertTo val{}; + bool parse_result = (!input.empty()) ? lexical_cast(input, val) : true; + if(parse_result) { + output = val; + } + return parse_result; +} + +/// Assign a value from a lexical cast through constructing a value and move assigning it +template < + typename AssignTo, + typename ConvertTo, + enable_if_t::value && !std::is_assignable::value && + std::is_move_assignable::value, + detail::enabler> = detail::dummy> +bool lexical_assign(const std::string &input, AssignTo &output) { + ConvertTo val{}; + bool parse_result = input.empty() ? true : lexical_cast(input, val); + if(parse_result) { + output = AssignTo(val); // use () form of constructor to allow some implicit conversions + } + return parse_result; +} + +/// primary lexical conversion operation, 1 string to 1 type of some kind +template ::value <= object_category::other && + classify_object::value <= object_category::wrapper_value, + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + return lexical_assign(strings[0], output); +} + +/// Lexical conversion if there is only one element but the conversion type is for two, then call a two element +/// constructor +template ::value <= 2) && expected_count::value == 1 && + is_tuple_like::value && type_count_base::value == 2, + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + // the remove const is to handle pair types coming from a container + using FirstType = typename std::remove_const::type>::type; + using SecondType = typename std::tuple_element<1, ConvertTo>::type; + FirstType v1; + SecondType v2; + bool retval = lexical_assign(strings[0], v1); + if(strings.size() > 1) { + retval = retval && lexical_assign(strings[1], v2); + } + if(retval) { + output = AssignTo{v1, v2}; + } + return retval; +} + +/// Lexical conversion of a container types of single elements +template ::value && is_mutable_container::value && + type_count::value == 1, + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + output.erase(output.begin(), output.end()); + if(strings.empty()) { + return true; + } + if(strings.size() == 1 && strings[0] == "{}") { + return true; + } + bool skip_remaining = false; + if(strings.size() == 2 && strings[0] == "{}" && is_separator(strings[1])) { + skip_remaining = true; + } + for(const auto &elem : strings) { + typename AssignTo::value_type out; + bool retval = lexical_assign(elem, out); + if(!retval) { + return false; + } + output.insert(output.end(), std::move(out)); + if(skip_remaining) { + break; + } + } + return (!output.empty()); +} + +/// Lexical conversion for complex types +template ::value, detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + + if(strings.size() >= 2 && !strings[1].empty()) { + using XC2 = typename wrapped_type::type; + XC2 x{0.0}, y{0.0}; + auto str1 = strings[1]; + if(str1.back() == 'i' || str1.back() == 'j') { + str1.pop_back(); + } + auto worked = lexical_cast(strings[0], x) && lexical_cast(str1, y); + if(worked) { + output = ConvertTo{x, y}; + } + return worked; + } + return lexical_assign(strings[0], output); +} + +/// Conversion to a vector type using a particular single type as the conversion type +template ::value && (expected_count::value == 1) && + (type_count::value == 1), + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + bool retval = true; + output.clear(); + output.reserve(strings.size()); + for(const auto &elem : strings) { + + output.emplace_back(); + retval = retval && lexical_assign(elem, output.back()); + } + return (!output.empty()) && retval; +} + +// forward declaration + +/// Lexical conversion of a container types with conversion type of two elements +template ::value && is_mutable_container::value && + type_count_base::value == 2, + detail::enabler> = detail::dummy> +bool lexical_conversion(std::vector strings, AssignTo &output); + +/// Lexical conversion of a vector types with type_size >2 forward declaration +template ::value && is_mutable_container::value && + type_count_base::value != 2 && + ((type_count::value > 2) || + (type_count::value > type_count_base::value)), + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output); + +/// Conversion for tuples +template ::value && is_tuple_like::value && + (type_count_base::value != type_count::value || + type_count::value > 2), + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output); // forward declaration + +/// Conversion for operations where the assigned type is some class but the conversion is a mutable container or large +/// tuple +template ::value && !is_mutable_container::value && + classify_object::value != object_category::wrapper_value && + (is_mutable_container::value || type_count::value > 2), + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + + if(strings.size() > 1 || (!strings.empty() && !(strings.front().empty()))) { + ConvertTo val; + auto retval = lexical_conversion(strings, val); + output = AssignTo{val}; + return retval; + } + output = AssignTo{}; + return true; +} + +/// function template for converting tuples if the static Index is greater than the tuple size +template +inline typename std::enable_if<(I >= type_count_base::value), bool>::type +tuple_conversion(const std::vector &, AssignTo &) { + return true; +} + +/// Conversion of a tuple element where the type size ==1 and not a mutable container +template +inline typename std::enable_if::value && type_count::value == 1, bool>::type +tuple_type_conversion(std::vector &strings, AssignTo &output) { + auto retval = lexical_assign(strings[0], output); + strings.erase(strings.begin()); + return retval; +} + +/// Conversion of a tuple element where the type size !=1 but the size is fixed and not a mutable container +template +inline typename std::enable_if::value && (type_count::value > 1) && + type_count::value == type_count_min::value, + bool>::type +tuple_type_conversion(std::vector &strings, AssignTo &output) { + auto retval = lexical_conversion(strings, output); + strings.erase(strings.begin(), strings.begin() + type_count::value); + return retval; +} + +/// Conversion of a tuple element where the type is a mutable container or a type with different min and max type sizes +template +inline typename std::enable_if::value || + type_count::value != type_count_min::value, + bool>::type +tuple_type_conversion(std::vector &strings, AssignTo &output) { + + std::size_t index{subtype_count_min::value}; + const std::size_t mx_count{subtype_count::value}; + const std::size_t mx{(std::min)(mx_count, strings.size() - 1)}; + + while(index < mx) { + if(is_separator(strings[index])) { + break; + } + ++index; + } + bool retval = lexical_conversion( + std::vector(strings.begin(), strings.begin() + static_cast(index)), output); + if(strings.size() > index) { + strings.erase(strings.begin(), strings.begin() + static_cast(index) + 1); + } else { + strings.clear(); + } + return retval; +} + +/// Tuple conversion operation +template +inline typename std::enable_if<(I < type_count_base::value), bool>::type +tuple_conversion(std::vector strings, AssignTo &output) { + bool retval = true; + using ConvertToElement = typename std:: + conditional::value, typename std::tuple_element::type, ConvertTo>::type; + if(!strings.empty()) { + retval = retval && tuple_type_conversion::type, ConvertToElement>( + strings, std::get(output)); + } + retval = retval && tuple_conversion(std::move(strings), output); + return retval; +} + +/// Lexical conversion of a container types with tuple elements of size 2 +template ::value && is_mutable_container::value && + type_count_base::value == 2, + detail::enabler>> +bool lexical_conversion(std::vector strings, AssignTo &output) { + output.clear(); + while(!strings.empty()) { + + typename std::remove_const::type>::type v1; + typename std::tuple_element<1, typename ConvertTo::value_type>::type v2; + bool retval = tuple_type_conversion(strings, v1); + if(!strings.empty()) { + retval = retval && tuple_type_conversion(strings, v2); + } + if(retval) { + output.insert(output.end(), typename AssignTo::value_type{v1, v2}); + } else { + return false; + } + } + return (!output.empty()); +} + +/// lexical conversion of tuples with type count>2 or tuples of types of some element with a type size>=2 +template ::value && is_tuple_like::value && + (type_count_base::value != type_count::value || + type_count::value > 2), + detail::enabler>> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + static_assert( + !is_tuple_like::value || type_count_base::value == type_count_base::value, + "if the conversion type is defined as a tuple it must be the same size as the type you are converting to"); + return tuple_conversion(strings, output); +} + +/// Lexical conversion of a vector types for everything but tuples of two elements and types of size 1 +template ::value && is_mutable_container::value && + type_count_base::value != 2 && + ((type_count::value > 2) || + (type_count::value > type_count_base::value)), + detail::enabler>> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + bool retval = true; + output.clear(); + std::vector temp; + std::size_t ii{0}; + std::size_t icount{0}; + std::size_t xcm{type_count::value}; + auto ii_max = strings.size(); + while(ii < ii_max) { + temp.push_back(strings[ii]); + ++ii; + ++icount; + if(icount == xcm || is_separator(temp.back()) || ii == ii_max) { + if(static_cast(xcm) > type_count_min::value && is_separator(temp.back())) { + temp.pop_back(); + } + typename AssignTo::value_type temp_out; + retval = retval && + lexical_conversion(temp, temp_out); + temp.clear(); + if(!retval) { + return false; + } + output.insert(output.end(), std::move(temp_out)); + icount = 0; + } + } + return retval; +} + +/// conversion for wrapper types +template ::value == object_category::wrapper_value && + std::is_assignable::value, + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + if(strings.empty() || strings.front().empty()) { + output = ConvertTo{}; + return true; + } + typename ConvertTo::value_type val; + if(lexical_conversion(strings, val)) { + output = ConvertTo{val}; + return true; + } + return false; +} + +/// conversion for wrapper types +template ::value == object_category::wrapper_value && + !std::is_assignable::value, + detail::enabler> = detail::dummy> +bool lexical_conversion(const std::vector &strings, AssignTo &output) { + using ConvertType = typename ConvertTo::value_type; + if(strings.empty() || strings.front().empty()) { + output = ConvertType{}; + return true; + } + ConvertType val; + if(lexical_conversion(strings, val)) { + output = val; + return true; + } + return false; +} + +/// Sum a vector of strings +inline std::string sum_string_vector(const std::vector &values) { + double val{0.0}; + bool fail{false}; + std::string output; + for(const auto &arg : values) { + double tv{0.0}; + auto comp = lexical_cast(arg, tv); + if(!comp) { + try { + tv = static_cast(detail::to_flag_value(arg)); + } catch(const std::exception &) { + fail = true; + break; + } + } + val += tv; + } + if(fail) { + for(const auto &arg : values) { + output.append(arg); + } + } else { + std::ostringstream out; + out.precision(16); + out << val; + output = out.str(); + } + return output; +} + +} // namespace detail + + + +namespace detail { + +// Returns false if not a short option. Otherwise, sets opt name and rest and returns true +CLI11_INLINE bool split_short(const std::string ¤t, std::string &name, std::string &rest); + +// Returns false if not a long option. Otherwise, sets opt name and other side of = and returns true +CLI11_INLINE bool split_long(const std::string ¤t, std::string &name, std::string &value); + +// Returns false if not a windows style option. Otherwise, sets opt name and value and returns true +CLI11_INLINE bool split_windows_style(const std::string ¤t, std::string &name, std::string &value); + +// Splits a string into multiple long and short names +CLI11_INLINE std::vector split_names(std::string current); + +/// extract default flag values either {def} or starting with a ! +CLI11_INLINE std::vector> get_default_flag_values(const std::string &str); + +/// Get a vector of short names, one of long names, and a single name +CLI11_INLINE std::tuple, std::vector, std::string> +get_names(const std::vector &input); + +} // namespace detail + + + +namespace detail { + +CLI11_INLINE bool split_short(const std::string ¤t, std::string &name, std::string &rest) { + if(current.size() > 1 && current[0] == '-' && valid_first_char(current[1])) { + name = current.substr(1, 1); + rest = current.substr(2); + return true; + } + return false; +} + +CLI11_INLINE bool split_long(const std::string ¤t, std::string &name, std::string &value) { + if(current.size() > 2 && current.compare(0, 2, "--") == 0 && valid_first_char(current[2])) { + auto loc = current.find_first_of('='); + if(loc != std::string::npos) { + name = current.substr(2, loc - 2); + value = current.substr(loc + 1); + } else { + name = current.substr(2); + value = ""; + } + return true; + } + return false; +} + +CLI11_INLINE bool split_windows_style(const std::string ¤t, std::string &name, std::string &value) { + if(current.size() > 1 && current[0] == '/' && valid_first_char(current[1])) { + auto loc = current.find_first_of(':'); + if(loc != std::string::npos) { + name = current.substr(1, loc - 1); + value = current.substr(loc + 1); + } else { + name = current.substr(1); + value = ""; + } + return true; + } + return false; +} + +CLI11_INLINE std::vector split_names(std::string current) { + std::vector output; + std::size_t val = 0; + while((val = current.find(',')) != std::string::npos) { + output.push_back(trim_copy(current.substr(0, val))); + current = current.substr(val + 1); + } + output.push_back(trim_copy(current)); + return output; +} + +CLI11_INLINE std::vector> get_default_flag_values(const std::string &str) { + std::vector flags = split_names(str); + flags.erase(std::remove_if(flags.begin(), + flags.end(), + [](const std::string &name) { + return ((name.empty()) || (!(((name.find_first_of('{') != std::string::npos) && + (name.back() == '}')) || + (name[0] == '!')))); + }), + flags.end()); + std::vector> output; + output.reserve(flags.size()); + for(auto &flag : flags) { + auto def_start = flag.find_first_of('{'); + std::string defval = "false"; + if((def_start != std::string::npos) && (flag.back() == '}')) { + defval = flag.substr(def_start + 1); + defval.pop_back(); + flag.erase(def_start, std::string::npos); // NOLINT(readability-suspicious-call-argument) + } + flag.erase(0, flag.find_first_not_of("-!")); + output.emplace_back(flag, defval); + } + return output; +} + +CLI11_INLINE std::tuple, std::vector, std::string> +get_names(const std::vector &input) { + + std::vector short_names; + std::vector long_names; + std::string pos_name; + + for(std::string name : input) { + if(name.length() == 0) { + continue; + } + if(name.length() > 1 && name[0] == '-' && name[1] != '-') { + if(name.length() == 2 && valid_first_char(name[1])) + short_names.emplace_back(1, name[1]); + else if(name.length() > 2) + throw BadNameString::MissingDash(name); + else + throw BadNameString::OneCharName(name); + } else if(name.length() > 2 && name.substr(0, 2) == "--") { + name = name.substr(2); + if(valid_name_string(name)) + long_names.push_back(name); + else + throw BadNameString::BadLongName(name); + } else if(name == "-" || name == "--") { + throw BadNameString::DashesOnly(name); + } else { + if(pos_name.length() > 0) + throw BadNameString::MultiPositionalNames(name); + pos_name = name; + } + } + + return std::make_tuple(short_names, long_names, pos_name); +} + +} // namespace detail + + + +class App; + +/// Holds values to load into Options +struct ConfigItem { + /// This is the list of parents + std::vector parents{}; + + /// This is the name + std::string name{}; + + /// Listing of inputs + std::vector inputs{}; + + /// The list of parents and name joined by "." + CLI11_NODISCARD std::string fullname() const { + std::vector tmp = parents; + tmp.emplace_back(name); + return detail::join(tmp, "."); + } +}; + +/// This class provides a converter for configuration files. +class Config { + protected: + std::vector items{}; + + public: + /// Convert an app into a configuration + virtual std::string to_config(const App *, bool, bool, std::string) const = 0; + + /// Convert a configuration into an app + virtual std::vector from_config(std::istream &) const = 0; + + /// Get a flag value + CLI11_NODISCARD virtual std::string to_flag(const ConfigItem &item) const { + if(item.inputs.size() == 1) { + return item.inputs.at(0); + } + if(item.inputs.empty()) { + return "{}"; + } + throw ConversionError::TooManyInputsFlag(item.fullname()); // LCOV_EXCL_LINE + } + + /// Parse a config file, throw an error (ParseError:ConfigParseError or FileError) on failure + CLI11_NODISCARD std::vector from_file(const std::string &name) const { + std::ifstream input{name}; + if(!input.good()) + throw FileError::Missing(name); + + return from_config(input); + } + + /// Virtual destructor + virtual ~Config() = default; +}; + +/// This converter works with INI/TOML files; to write INI files use ConfigINI +class ConfigBase : public Config { + protected: + /// the character used for comments + char commentChar = '#'; + /// the character used to start an array '\0' is a default to not use + char arrayStart = '['; + /// the character used to end an array '\0' is a default to not use + char arrayEnd = ']'; + /// the character used to separate elements in an array + char arraySeparator = ','; + /// the character used separate the name from the value + char valueDelimiter = '='; + /// the character to use around strings + char stringQuote = '"'; + /// the character to use around single characters + char characterQuote = '\''; + /// the maximum number of layers to allow + uint8_t maximumLayers{255}; + /// the separator used to separator parent layers + char parentSeparatorChar{'.'}; + /// Specify the configuration index to use for arrayed sections + int16_t configIndex{-1}; + /// Specify the configuration section that should be used + std::string configSection{}; + + public: + std::string + to_config(const App * /*app*/, bool default_also, bool write_description, std::string prefix) const override; + + std::vector from_config(std::istream &input) const override; + /// Specify the configuration for comment characters + ConfigBase *comment(char cchar) { + commentChar = cchar; + return this; + } + /// Specify the start and end characters for an array + ConfigBase *arrayBounds(char aStart, char aEnd) { + arrayStart = aStart; + arrayEnd = aEnd; + return this; + } + /// Specify the delimiter character for an array + ConfigBase *arrayDelimiter(char aSep) { + arraySeparator = aSep; + return this; + } + /// Specify the delimiter between a name and value + ConfigBase *valueSeparator(char vSep) { + valueDelimiter = vSep; + return this; + } + /// Specify the quote characters used around strings and characters + ConfigBase *quoteCharacter(char qString, char qChar) { + stringQuote = qString; + characterQuote = qChar; + return this; + } + /// Specify the maximum number of parents + ConfigBase *maxLayers(uint8_t layers) { + maximumLayers = layers; + return this; + } + /// Specify the separator to use for parent layers + ConfigBase *parentSeparator(char sep) { + parentSeparatorChar = sep; + return this; + } + /// get a reference to the configuration section + std::string §ionRef() { return configSection; } + /// get the section + CLI11_NODISCARD const std::string §ion() const { return configSection; } + /// specify a particular section of the configuration file to use + ConfigBase *section(const std::string §ionName) { + configSection = sectionName; + return this; + } + + /// get a reference to the configuration index + int16_t &indexRef() { return configIndex; } + /// get the section index + CLI11_NODISCARD int16_t index() const { return configIndex; } + /// specify a particular index in the section to use (-1) for all sections to use + ConfigBase *index(int16_t sectionIndex) { + configIndex = sectionIndex; + return this; + } +}; + +/// the default Config is the TOML file format +using ConfigTOML = ConfigBase; + +/// ConfigINI generates a "standard" INI compliant output +class ConfigINI : public ConfigTOML { + + public: + ConfigINI() { + commentChar = ';'; + arrayStart = '\0'; + arrayEnd = '\0'; + arraySeparator = ' '; + valueDelimiter = '='; + } +}; + + + +class Option; + +/// @defgroup validator_group Validators + +/// @brief Some validators that are provided +/// +/// These are simple `std::string(const std::string&)` validators that are useful. They return +/// a string if the validation fails. A custom struct is provided, as well, with the same user +/// semantics, but with the ability to provide a new type name. +/// @{ + +/// +class Validator { + protected: + /// This is the description function, if empty the description_ will be used + std::function desc_function_{[]() { return std::string{}; }}; + + /// This is the base function that is to be called. + /// Returns a string error message if validation fails. + std::function func_{[](std::string &) { return std::string{}; }}; + /// The name for search purposes of the Validator + std::string name_{}; + /// A Validator will only apply to an indexed value (-1 is all elements) + int application_index_ = -1; + /// Enable for Validator to allow it to be disabled if need be + bool active_{true}; + /// specify that a validator should not modify the input + bool non_modifying_{false}; + + Validator(std::string validator_desc, std::function func) + : desc_function_([validator_desc]() { return validator_desc; }), func_(std::move(func)) {} + + public: + Validator() = default; + /// Construct a Validator with just the description string + explicit Validator(std::string validator_desc) : desc_function_([validator_desc]() { return validator_desc; }) {} + /// Construct Validator from basic information + Validator(std::function op, std::string validator_desc, std::string validator_name = "") + : desc_function_([validator_desc]() { return validator_desc; }), func_(std::move(op)), + name_(std::move(validator_name)) {} + /// Set the Validator operation function + Validator &operation(std::function op) { + func_ = std::move(op); + return *this; + } + /// This is the required operator for a Validator - provided to help + /// users (CLI11 uses the member `func` directly) + std::string operator()(std::string &str) const; + + /// This is the required operator for a Validator - provided to help + /// users (CLI11 uses the member `func` directly) + std::string operator()(const std::string &str) const { + std::string value = str; + return (active_) ? func_(value) : std::string{}; + } + + /// Specify the type string + Validator &description(std::string validator_desc) { + desc_function_ = [validator_desc]() { return validator_desc; }; + return *this; + } + /// Specify the type string + CLI11_NODISCARD Validator description(std::string validator_desc) const; + + /// Generate type description information for the Validator + CLI11_NODISCARD std::string get_description() const { + if(active_) { + return desc_function_(); + } + return std::string{}; + } + /// Specify the type string + Validator &name(std::string validator_name) { + name_ = std::move(validator_name); + return *this; + } + /// Specify the type string + CLI11_NODISCARD Validator name(std::string validator_name) const { + Validator newval(*this); + newval.name_ = std::move(validator_name); + return newval; + } + /// Get the name of the Validator + CLI11_NODISCARD const std::string &get_name() const { return name_; } + /// Specify whether the Validator is active or not + Validator &active(bool active_val = true) { + active_ = active_val; + return *this; + } + /// Specify whether the Validator is active or not + CLI11_NODISCARD Validator active(bool active_val = true) const { + Validator newval(*this); + newval.active_ = active_val; + return newval; + } + + /// Specify whether the Validator can be modifying or not + Validator &non_modifying(bool no_modify = true) { + non_modifying_ = no_modify; + return *this; + } + /// Specify the application index of a validator + Validator &application_index(int app_index) { + application_index_ = app_index; + return *this; + } + /// Specify the application index of a validator + CLI11_NODISCARD Validator application_index(int app_index) const { + Validator newval(*this); + newval.application_index_ = app_index; + return newval; + } + /// Get the current value of the application index + CLI11_NODISCARD int get_application_index() const { return application_index_; } + /// Get a boolean if the validator is active + CLI11_NODISCARD bool get_active() const { return active_; } + + /// Get a boolean if the validator is allowed to modify the input returns true if it can modify the input + CLI11_NODISCARD bool get_modifying() const { return !non_modifying_; } + + /// Combining validators is a new validator. Type comes from left validator if function, otherwise only set if the + /// same. + Validator operator&(const Validator &other) const; + + /// Combining validators is a new validator. Type comes from left validator if function, otherwise only set if the + /// same. + Validator operator|(const Validator &other) const; + + /// Create a validator that fails when a given validator succeeds + Validator operator!() const; + + private: + void _merge_description(const Validator &val1, const Validator &val2, const std::string &merger); +}; + +/// Class wrapping some of the accessors of Validator +class CustomValidator : public Validator { + public: +}; +// The implementation of the built in validators is using the Validator class; +// the user is only expected to use the const (static) versions (since there's no setup). +// Therefore, this is in detail. +namespace detail { + +/// CLI enumeration of different file types +enum class path_type { nonexistent, file, directory }; + +/// get the type of the path from a file name +CLI11_INLINE path_type check_path(const char *file) noexcept; + +/// Check for an existing file (returns error message if check fails) +class ExistingFileValidator : public Validator { + public: + ExistingFileValidator(); +}; + +/// Check for an existing directory (returns error message if check fails) +class ExistingDirectoryValidator : public Validator { + public: + ExistingDirectoryValidator(); +}; + +/// Check for an existing path +class ExistingPathValidator : public Validator { + public: + ExistingPathValidator(); +}; + +/// Check for an non-existing path +class NonexistentPathValidator : public Validator { + public: + NonexistentPathValidator(); +}; + +/// Validate the given string is a legal ipv4 address +class IPV4Validator : public Validator { + public: + IPV4Validator(); +}; + +} // namespace detail + +// Static is not needed here, because global const implies static. + +/// Check for existing file (returns error message if check fails) +const detail::ExistingFileValidator ExistingFile; + +/// Check for an existing directory (returns error message if check fails) +const detail::ExistingDirectoryValidator ExistingDirectory; + +/// Check for an existing path +const detail::ExistingPathValidator ExistingPath; + +/// Check for an non-existing path +const detail::NonexistentPathValidator NonexistentPath; + +/// Check for an IP4 address +const detail::IPV4Validator ValidIPV4; + +/// Validate the input as a particular type +template class TypeValidator : public Validator { + public: + explicit TypeValidator(const std::string &validator_name) + : Validator(validator_name, [](std::string &input_string) { + using CLI::detail::lexical_cast; + auto val = DesiredType(); + if(!lexical_cast(input_string, val)) { + return std::string("Failed parsing ") + input_string + " as a " + detail::type_name(); + } + return std::string(); + }) {} + TypeValidator() : TypeValidator(detail::type_name()) {} +}; + +/// Check for a number +const TypeValidator Number("NUMBER"); + +/// Modify a path if the file is a particular default location, can be used as Check or transform +/// with the error return optionally disabled +class FileOnDefaultPath : public Validator { + public: + explicit FileOnDefaultPath(std::string default_path, bool enableErrorReturn = true); +}; + +/// Produce a range (factory). Min and max are inclusive. +class Range : public Validator { + public: + /// This produces a range with min and max inclusive. + /// + /// Note that the constructor is templated, but the struct is not, so C++17 is not + /// needed to provide nice syntax for Range(a,b). + template + Range(T min_val, T max_val, const std::string &validator_name = std::string{}) : Validator(validator_name) { + if(validator_name.empty()) { + std::stringstream out; + out << detail::type_name() << " in [" << min_val << " - " << max_val << "]"; + description(out.str()); + } + + func_ = [min_val, max_val](std::string &input) { + using CLI::detail::lexical_cast; + T val; + bool converted = lexical_cast(input, val); + if((!converted) || (val < min_val || val > max_val)) { + std::stringstream out; + out << "Value " << input << " not in range ["; + out << min_val << " - " << max_val << "]"; + return out.str(); + } + return std::string{}; + }; + } + + /// Range of one value is 0 to value + template + explicit Range(T max_val, const std::string &validator_name = std::string{}) + : Range(static_cast(0), max_val, validator_name) {} +}; + +/// Check for a non negative number +const Range NonNegativeNumber((std::numeric_limits::max)(), "NONNEGATIVE"); + +/// Check for a positive valued number (val>0.0), ::min here is the smallest positive number +const Range PositiveNumber((std::numeric_limits::min)(), (std::numeric_limits::max)(), "POSITIVE"); + +/// Produce a bounded range (factory). Min and max are inclusive. +class Bound : public Validator { + public: + /// This bounds a value with min and max inclusive. + /// + /// Note that the constructor is templated, but the struct is not, so C++17 is not + /// needed to provide nice syntax for Range(a,b). + template Bound(T min_val, T max_val) { + std::stringstream out; + out << detail::type_name() << " bounded to [" << min_val << " - " << max_val << "]"; + description(out.str()); + + func_ = [min_val, max_val](std::string &input) { + using CLI::detail::lexical_cast; + T val; + bool converted = lexical_cast(input, val); + if(!converted) { + return std::string("Value ") + input + " could not be converted"; + } + if(val < min_val) + input = detail::to_string(min_val); + else if(val > max_val) + input = detail::to_string(max_val); + + return std::string{}; + }; + } + + /// Range of one value is 0 to value + template explicit Bound(T max_val) : Bound(static_cast(0), max_val) {} +}; + +namespace detail { +template ::type>::value, detail::enabler> = detail::dummy> +auto smart_deref(T value) -> decltype(*value) { + return *value; +} + +template < + typename T, + enable_if_t::type>::value, detail::enabler> = detail::dummy> +typename std::remove_reference::type &smart_deref(T &value) { + return value; +} +/// Generate a string representation of a set +template std::string generate_set(const T &set) { + using element_t = typename detail::element_type::type; + using iteration_type_t = typename detail::pair_adaptor::value_type; // the type of the object pair + std::string out(1, '{'); + out.append(detail::join( + detail::smart_deref(set), + [](const iteration_type_t &v) { return detail::pair_adaptor::first(v); }, + ",")); + out.push_back('}'); + return out; +} + +/// Generate a string representation of a map +template std::string generate_map(const T &map, bool key_only = false) { + using element_t = typename detail::element_type::type; + using iteration_type_t = typename detail::pair_adaptor::value_type; // the type of the object pair + std::string out(1, '{'); + out.append(detail::join( + detail::smart_deref(map), + [key_only](const iteration_type_t &v) { + std::string res{detail::to_string(detail::pair_adaptor::first(v))}; + + if(!key_only) { + res.append("->"); + res += detail::to_string(detail::pair_adaptor::second(v)); + } + return res; + }, + ",")); + out.push_back('}'); + return out; +} + +template struct has_find { + template + static auto test(int) -> decltype(std::declval().find(std::declval()), std::true_type()); + template static auto test(...) -> decltype(std::false_type()); + + static const auto value = decltype(test(0))::value; + using type = std::integral_constant; +}; + +/// A search function +template ::value, detail::enabler> = detail::dummy> +auto search(const T &set, const V &val) -> std::pair { + using element_t = typename detail::element_type::type; + auto &setref = detail::smart_deref(set); + auto it = std::find_if(std::begin(setref), std::end(setref), [&val](decltype(*std::begin(setref)) v) { + return (detail::pair_adaptor::first(v) == val); + }); + return {(it != std::end(setref)), it}; +} + +/// A search function that uses the built in find function +template ::value, detail::enabler> = detail::dummy> +auto search(const T &set, const V &val) -> std::pair { + auto &setref = detail::smart_deref(set); + auto it = setref.find(val); + return {(it != std::end(setref)), it}; +} + +/// A search function with a filter function +template +auto search(const T &set, const V &val, const std::function &filter_function) + -> std::pair { + using element_t = typename detail::element_type::type; + // do the potentially faster first search + auto res = search(set, val); + if((res.first) || (!(filter_function))) { + return res; + } + // if we haven't found it do the longer linear search with all the element translations + auto &setref = detail::smart_deref(set); + auto it = std::find_if(std::begin(setref), std::end(setref), [&](decltype(*std::begin(setref)) v) { + V a{detail::pair_adaptor::first(v)}; + a = filter_function(a); + return (a == val); + }); + return {(it != std::end(setref)), it}; +} + +// the following suggestion was made by Nikita Ofitserov(@himikof) +// done in templates to prevent compiler warnings on negation of unsigned numbers + +/// Do a check for overflow on signed numbers +template +inline typename std::enable_if::value, T>::type overflowCheck(const T &a, const T &b) { + if((a > 0) == (b > 0)) { + return ((std::numeric_limits::max)() / (std::abs)(a) < (std::abs)(b)); + } + return ((std::numeric_limits::min)() / (std::abs)(a) > -(std::abs)(b)); +} +/// Do a check for overflow on unsigned numbers +template +inline typename std::enable_if::value, T>::type overflowCheck(const T &a, const T &b) { + return ((std::numeric_limits::max)() / a < b); +} + +/// Performs a *= b; if it doesn't cause integer overflow. Returns false otherwise. +template typename std::enable_if::value, bool>::type checked_multiply(T &a, T b) { + if(a == 0 || b == 0 || a == 1 || b == 1) { + a *= b; + return true; + } + if(a == (std::numeric_limits::min)() || b == (std::numeric_limits::min)()) { + return false; + } + if(overflowCheck(a, b)) { + return false; + } + a *= b; + return true; +} + +/// Performs a *= b; if it doesn't equal infinity. Returns false otherwise. +template +typename std::enable_if::value, bool>::type checked_multiply(T &a, T b) { + T c = a * b; + if(std::isinf(c) && !std::isinf(a) && !std::isinf(b)) { + return false; + } + a = c; + return true; +} + +} // namespace detail +/// Verify items are in a set +class IsMember : public Validator { + public: + using filter_fn_t = std::function; + + /// This allows in-place construction using an initializer list + template + IsMember(std::initializer_list values, Args &&...args) + : IsMember(std::vector(values), std::forward(args)...) {} + + /// This checks to see if an item is in a set (empty function) + template explicit IsMember(T &&set) : IsMember(std::forward(set), nullptr) {} + + /// This checks to see if an item is in a set: pointer or copy version. You can pass in a function that will filter + /// both sides of the comparison before computing the comparison. + template explicit IsMember(T set, F filter_function) { + + // Get the type of the contained item - requires a container have ::value_type + // if the type does not have first_type and second_type, these are both value_type + using element_t = typename detail::element_type::type; // Removes (smart) pointers if needed + using item_t = typename detail::pair_adaptor::first_type; // Is value_type if not a map + + using local_item_t = typename IsMemberType::type; // This will convert bad types to good ones + // (const char * to std::string) + + // Make a local copy of the filter function, using a std::function if not one already + std::function filter_fn = filter_function; + + // This is the type name for help, it will take the current version of the set contents + desc_function_ = [set]() { return detail::generate_set(detail::smart_deref(set)); }; + + // This is the function that validates + // It stores a copy of the set pointer-like, so shared_ptr will stay alive + func_ = [set, filter_fn](std::string &input) { + using CLI::detail::lexical_cast; + local_item_t b; + if(!lexical_cast(input, b)) { + throw ValidationError(input); // name is added later + } + if(filter_fn) { + b = filter_fn(b); + } + auto res = detail::search(set, b, filter_fn); + if(res.first) { + // Make sure the version in the input string is identical to the one in the set + if(filter_fn) { + input = detail::value_string(detail::pair_adaptor::first(*(res.second))); + } + + // Return empty error string (success) + return std::string{}; + } + + // If you reach this point, the result was not found + return input + " not in " + detail::generate_set(detail::smart_deref(set)); + }; + } + + /// You can pass in as many filter functions as you like, they nest (string only currently) + template + IsMember(T &&set, filter_fn_t filter_fn_1, filter_fn_t filter_fn_2, Args &&...other) + : IsMember( + std::forward(set), + [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); }, + other...) {} +}; + +/// definition of the default transformation object +template using TransformPairs = std::vector>; + +/// Translate named items to other or a value set +class Transformer : public Validator { + public: + using filter_fn_t = std::function; + + /// This allows in-place construction + template + Transformer(std::initializer_list> values, Args &&...args) + : Transformer(TransformPairs(values), std::forward(args)...) {} + + /// direct map of std::string to std::string + template explicit Transformer(T &&mapping) : Transformer(std::forward(mapping), nullptr) {} + + /// This checks to see if an item is in a set: pointer or copy version. You can pass in a function that will filter + /// both sides of the comparison before computing the comparison. + template explicit Transformer(T mapping, F filter_function) { + + static_assert(detail::pair_adaptor::type>::value, + "mapping must produce value pairs"); + // Get the type of the contained item - requires a container have ::value_type + // if the type does not have first_type and second_type, these are both value_type + using element_t = typename detail::element_type::type; // Removes (smart) pointers if needed + using item_t = typename detail::pair_adaptor::first_type; // Is value_type if not a map + using local_item_t = typename IsMemberType::type; // Will convert bad types to good ones + // (const char * to std::string) + + // Make a local copy of the filter function, using a std::function if not one already + std::function filter_fn = filter_function; + + // This is the type name for help, it will take the current version of the set contents + desc_function_ = [mapping]() { return detail::generate_map(detail::smart_deref(mapping)); }; + + func_ = [mapping, filter_fn](std::string &input) { + using CLI::detail::lexical_cast; + local_item_t b; + if(!lexical_cast(input, b)) { + return std::string(); + // there is no possible way we can match anything in the mapping if we can't convert so just return + } + if(filter_fn) { + b = filter_fn(b); + } + auto res = detail::search(mapping, b, filter_fn); + if(res.first) { + input = detail::value_string(detail::pair_adaptor::second(*res.second)); + } + return std::string{}; + }; + } + + /// You can pass in as many filter functions as you like, they nest + template + Transformer(T &&mapping, filter_fn_t filter_fn_1, filter_fn_t filter_fn_2, Args &&...other) + : Transformer( + std::forward(mapping), + [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); }, + other...) {} +}; + +/// translate named items to other or a value set +class CheckedTransformer : public Validator { + public: + using filter_fn_t = std::function; + + /// This allows in-place construction + template + CheckedTransformer(std::initializer_list> values, Args &&...args) + : CheckedTransformer(TransformPairs(values), std::forward(args)...) {} + + /// direct map of std::string to std::string + template explicit CheckedTransformer(T mapping) : CheckedTransformer(std::move(mapping), nullptr) {} + + /// This checks to see if an item is in a set: pointer or copy version. You can pass in a function that will filter + /// both sides of the comparison before computing the comparison. + template explicit CheckedTransformer(T mapping, F filter_function) { + + static_assert(detail::pair_adaptor::type>::value, + "mapping must produce value pairs"); + // Get the type of the contained item - requires a container have ::value_type + // if the type does not have first_type and second_type, these are both value_type + using element_t = typename detail::element_type::type; // Removes (smart) pointers if needed + using item_t = typename detail::pair_adaptor::first_type; // Is value_type if not a map + using local_item_t = typename IsMemberType::type; // Will convert bad types to good ones + // (const char * to std::string) + using iteration_type_t = typename detail::pair_adaptor::value_type; // the type of the object pair + + // Make a local copy of the filter function, using a std::function if not one already + std::function filter_fn = filter_function; + + auto tfunc = [mapping]() { + std::string out("value in "); + out += detail::generate_map(detail::smart_deref(mapping)) + " OR {"; + out += detail::join( + detail::smart_deref(mapping), + [](const iteration_type_t &v) { return detail::to_string(detail::pair_adaptor::second(v)); }, + ","); + out.push_back('}'); + return out; + }; + + desc_function_ = tfunc; + + func_ = [mapping, tfunc, filter_fn](std::string &input) { + using CLI::detail::lexical_cast; + local_item_t b; + bool converted = lexical_cast(input, b); + if(converted) { + if(filter_fn) { + b = filter_fn(b); + } + auto res = detail::search(mapping, b, filter_fn); + if(res.first) { + input = detail::value_string(detail::pair_adaptor::second(*res.second)); + return std::string{}; + } + } + for(const auto &v : detail::smart_deref(mapping)) { + auto output_string = detail::value_string(detail::pair_adaptor::second(v)); + if(output_string == input) { + return std::string(); + } + } + + return "Check " + input + " " + tfunc() + " FAILED"; + }; + } + + /// You can pass in as many filter functions as you like, they nest + template + CheckedTransformer(T &&mapping, filter_fn_t filter_fn_1, filter_fn_t filter_fn_2, Args &&...other) + : CheckedTransformer( + std::forward(mapping), + [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); }, + other...) {} +}; + +/// Helper function to allow ignore_case to be passed to IsMember or Transform +inline std::string ignore_case(std::string item) { return detail::to_lower(item); } + +/// Helper function to allow ignore_underscore to be passed to IsMember or Transform +inline std::string ignore_underscore(std::string item) { return detail::remove_underscore(item); } + +/// Helper function to allow checks to ignore spaces to be passed to IsMember or Transform +inline std::string ignore_space(std::string item) { + item.erase(std::remove(std::begin(item), std::end(item), ' '), std::end(item)); + item.erase(std::remove(std::begin(item), std::end(item), '\t'), std::end(item)); + return item; +} + +/// Multiply a number by a factor using given mapping. +/// Can be used to write transforms for SIZE or DURATION inputs. +/// +/// Example: +/// With mapping = `{"b"->1, "kb"->1024, "mb"->1024*1024}` +/// one can recognize inputs like "100", "12kb", "100 MB", +/// that will be automatically transformed to 100, 14448, 104857600. +/// +/// Output number type matches the type in the provided mapping. +/// Therefore, if it is required to interpret real inputs like "0.42 s", +/// the mapping should be of a type or . +class AsNumberWithUnit : public Validator { + public: + /// Adjust AsNumberWithUnit behavior. + /// CASE_SENSITIVE/CASE_INSENSITIVE controls how units are matched. + /// UNIT_OPTIONAL/UNIT_REQUIRED throws ValidationError + /// if UNIT_REQUIRED is set and unit literal is not found. + enum Options { + CASE_SENSITIVE = 0, + CASE_INSENSITIVE = 1, + UNIT_OPTIONAL = 0, + UNIT_REQUIRED = 2, + DEFAULT = CASE_INSENSITIVE | UNIT_OPTIONAL + }; + + template + explicit AsNumberWithUnit(std::map mapping, + Options opts = DEFAULT, + const std::string &unit_name = "UNIT") { + description(generate_description(unit_name, opts)); + validate_mapping(mapping, opts); + + // transform function + func_ = [mapping, opts](std::string &input) -> std::string { + Number num{}; + + detail::rtrim(input); + if(input.empty()) { + throw ValidationError("Input is empty"); + } + + // Find split position between number and prefix + auto unit_begin = input.end(); + while(unit_begin > input.begin() && std::isalpha(*(unit_begin - 1), std::locale())) { + --unit_begin; + } + + std::string unit{unit_begin, input.end()}; + input.resize(static_cast(std::distance(input.begin(), unit_begin))); + detail::trim(input); + + if(opts & UNIT_REQUIRED && unit.empty()) { + throw ValidationError("Missing mandatory unit"); + } + if(opts & CASE_INSENSITIVE) { + unit = detail::to_lower(unit); + } + if(unit.empty()) { + using CLI::detail::lexical_cast; + if(!lexical_cast(input, num)) { + throw ValidationError(std::string("Value ") + input + " could not be converted to " + + detail::type_name()); + } + // No need to modify input if no unit passed + return {}; + } + + // find corresponding factor + auto it = mapping.find(unit); + if(it == mapping.end()) { + throw ValidationError(unit + + " unit not recognized. " + "Allowed values: " + + detail::generate_map(mapping, true)); + } + + if(!input.empty()) { + using CLI::detail::lexical_cast; + bool converted = lexical_cast(input, num); + if(!converted) { + throw ValidationError(std::string("Value ") + input + " could not be converted to " + + detail::type_name()); + } + // perform safe multiplication + bool ok = detail::checked_multiply(num, it->second); + if(!ok) { + throw ValidationError(detail::to_string(num) + " multiplied by " + unit + + " factor would cause number overflow. Use smaller value."); + } + } else { + num = static_cast(it->second); + } + + input = detail::to_string(num); + + return {}; + }; + } + + private: + /// Check that mapping contains valid units. + /// Update mapping for CASE_INSENSITIVE mode. + template static void validate_mapping(std::map &mapping, Options opts) { + for(auto &kv : mapping) { + if(kv.first.empty()) { + throw ValidationError("Unit must not be empty."); + } + if(!detail::isalpha(kv.first)) { + throw ValidationError("Unit must contain only letters."); + } + } + + // make all units lowercase if CASE_INSENSITIVE + if(opts & CASE_INSENSITIVE) { + std::map lower_mapping; + for(auto &kv : mapping) { + auto s = detail::to_lower(kv.first); + if(lower_mapping.count(s)) { + throw ValidationError(std::string("Several matching lowercase unit representations are found: ") + + s); + } + lower_mapping[detail::to_lower(kv.first)] = kv.second; + } + mapping = std::move(lower_mapping); + } + } + + /// Generate description like this: NUMBER [UNIT] + template static std::string generate_description(const std::string &name, Options opts) { + std::stringstream out; + out << detail::type_name() << ' '; + if(opts & UNIT_REQUIRED) { + out << name; + } else { + out << '[' << name << ']'; + } + return out.str(); + } +}; + +inline AsNumberWithUnit::Options operator|(const AsNumberWithUnit::Options &a, const AsNumberWithUnit::Options &b) { + return static_cast(static_cast(a) | static_cast(b)); +} + +/// Converts a human-readable size string (with unit literal) to uin64_t size. +/// Example: +/// "100" => 100 +/// "1 b" => 100 +/// "10Kb" => 10240 // you can configure this to be interpreted as kilobyte (*1000) or kibibyte (*1024) +/// "10 KB" => 10240 +/// "10 kb" => 10240 +/// "10 kib" => 10240 // *i, *ib are always interpreted as *bibyte (*1024) +/// "10kb" => 10240 +/// "2 MB" => 2097152 +/// "2 EiB" => 2^61 // Units up to exibyte are supported +class AsSizeValue : public AsNumberWithUnit { + public: + using result_t = std::uint64_t; + + /// If kb_is_1000 is true, + /// interpret 'kb', 'k' as 1000 and 'kib', 'ki' as 1024 + /// (same applies to higher order units as well). + /// Otherwise, interpret all literals as factors of 1024. + /// The first option is formally correct, but + /// the second interpretation is more wide-spread + /// (see https://en.wikipedia.org/wiki/Binary_prefix). + explicit AsSizeValue(bool kb_is_1000); + + private: + /// Get mapping + static std::map init_mapping(bool kb_is_1000); + + /// Cache calculated mapping + static std::map get_mapping(bool kb_is_1000); +}; + +namespace detail { +/// Split a string into a program name and command line arguments +/// the string is assumed to contain a file name followed by other arguments +/// the return value contains is a pair with the first argument containing the program name and the second +/// everything else. +CLI11_INLINE std::pair split_program_name(std::string commandline); + +} // namespace detail +/// @} + + + + +CLI11_INLINE std::string Validator::operator()(std::string &str) const { + std::string retstring; + if(active_) { + if(non_modifying_) { + std::string value = str; + retstring = func_(value); + } else { + retstring = func_(str); + } + } + return retstring; +} + +CLI11_NODISCARD CLI11_INLINE Validator Validator::description(std::string validator_desc) const { + Validator newval(*this); + newval.desc_function_ = [validator_desc]() { return validator_desc; }; + return newval; +} + +CLI11_INLINE Validator Validator::operator&(const Validator &other) const { + Validator newval; + + newval._merge_description(*this, other, " AND "); + + // Give references (will make a copy in lambda function) + const std::function &f1 = func_; + const std::function &f2 = other.func_; + + newval.func_ = [f1, f2](std::string &input) { + std::string s1 = f1(input); + std::string s2 = f2(input); + if(!s1.empty() && !s2.empty()) + return std::string("(") + s1 + ") AND (" + s2 + ")"; + return s1 + s2; + }; + + newval.active_ = active_ && other.active_; + newval.application_index_ = application_index_; + return newval; +} + +CLI11_INLINE Validator Validator::operator|(const Validator &other) const { + Validator newval; + + newval._merge_description(*this, other, " OR "); + + // Give references (will make a copy in lambda function) + const std::function &f1 = func_; + const std::function &f2 = other.func_; + + newval.func_ = [f1, f2](std::string &input) { + std::string s1 = f1(input); + std::string s2 = f2(input); + if(s1.empty() || s2.empty()) + return std::string(); + + return std::string("(") + s1 + ") OR (" + s2 + ")"; + }; + newval.active_ = active_ && other.active_; + newval.application_index_ = application_index_; + return newval; +} + +CLI11_INLINE Validator Validator::operator!() const { + Validator newval; + const std::function &dfunc1 = desc_function_; + newval.desc_function_ = [dfunc1]() { + auto str = dfunc1(); + return (!str.empty()) ? std::string("NOT ") + str : std::string{}; + }; + // Give references (will make a copy in lambda function) + const std::function &f1 = func_; + + newval.func_ = [f1, dfunc1](std::string &test) -> std::string { + std::string s1 = f1(test); + if(s1.empty()) { + return std::string("check ") + dfunc1() + " succeeded improperly"; + } + return std::string{}; + }; + newval.active_ = active_; + newval.application_index_ = application_index_; + return newval; +} + +CLI11_INLINE void +Validator::_merge_description(const Validator &val1, const Validator &val2, const std::string &merger) { + + const std::function &dfunc1 = val1.desc_function_; + const std::function &dfunc2 = val2.desc_function_; + + desc_function_ = [=]() { + std::string f1 = dfunc1(); + std::string f2 = dfunc2(); + if((f1.empty()) || (f2.empty())) { + return f1 + f2; + } + return std::string(1, '(') + f1 + ')' + merger + '(' + f2 + ')'; + }; +} + +namespace detail { + +#if defined CLI11_HAS_FILESYSTEM && CLI11_HAS_FILESYSTEM > 0 +CLI11_INLINE path_type check_path(const char *file) noexcept { + std::error_code ec; + auto stat = std::filesystem::status(to_path(file), ec); + if(ec) { + return path_type::nonexistent; + } + switch(stat.type()) { + case std::filesystem::file_type::none: // LCOV_EXCL_LINE + case std::filesystem::file_type::not_found: + return path_type::nonexistent; + case std::filesystem::file_type::directory: + return path_type::directory; + case std::filesystem::file_type::symlink: + case std::filesystem::file_type::block: + case std::filesystem::file_type::character: + case std::filesystem::file_type::fifo: + case std::filesystem::file_type::socket: + case std::filesystem::file_type::regular: + case std::filesystem::file_type::unknown: + default: + return path_type::file; + } +} +#else +CLI11_INLINE path_type check_path(const char *file) noexcept { +#if defined(_MSC_VER) + struct __stat64 buffer; + if(_stat64(file, &buffer) == 0) { + return ((buffer.st_mode & S_IFDIR) != 0) ? path_type::directory : path_type::file; + } +#else + struct stat buffer; + if(stat(file, &buffer) == 0) { + return ((buffer.st_mode & S_IFDIR) != 0) ? path_type::directory : path_type::file; + } +#endif + return path_type::nonexistent; +} +#endif + +CLI11_INLINE ExistingFileValidator::ExistingFileValidator() : Validator("FILE") { + func_ = [](std::string &filename) { + auto path_result = check_path(filename.c_str()); + if(path_result == path_type::nonexistent) { + return "File does not exist: " + filename; + } + if(path_result == path_type::directory) { + return "File is actually a directory: " + filename; + } + return std::string(); + }; +} + +CLI11_INLINE ExistingDirectoryValidator::ExistingDirectoryValidator() : Validator("DIR") { + func_ = [](std::string &filename) { + auto path_result = check_path(filename.c_str()); + if(path_result == path_type::nonexistent) { + return "Directory does not exist: " + filename; + } + if(path_result == path_type::file) { + return "Directory is actually a file: " + filename; + } + return std::string(); + }; +} + +CLI11_INLINE ExistingPathValidator::ExistingPathValidator() : Validator("PATH(existing)") { + func_ = [](std::string &filename) { + auto path_result = check_path(filename.c_str()); + if(path_result == path_type::nonexistent) { + return "Path does not exist: " + filename; + } + return std::string(); + }; +} + +CLI11_INLINE NonexistentPathValidator::NonexistentPathValidator() : Validator("PATH(non-existing)") { + func_ = [](std::string &filename) { + auto path_result = check_path(filename.c_str()); + if(path_result != path_type::nonexistent) { + return "Path already exists: " + filename; + } + return std::string(); + }; +} + +CLI11_INLINE IPV4Validator::IPV4Validator() : Validator("IPV4") { + func_ = [](std::string &ip_addr) { + auto result = CLI::detail::split(ip_addr, '.'); + if(result.size() != 4) { + return std::string("Invalid IPV4 address must have four parts (") + ip_addr + ')'; + } + int num = 0; + for(const auto &var : result) { + using CLI::detail::lexical_cast; + bool retval = lexical_cast(var, num); + if(!retval) { + return std::string("Failed parsing number (") + var + ')'; + } + if(num < 0 || num > 255) { + return std::string("Each IP number must be between 0 and 255 ") + var; + } + } + return std::string(); + }; +} + +} // namespace detail + +CLI11_INLINE FileOnDefaultPath::FileOnDefaultPath(std::string default_path, bool enableErrorReturn) + : Validator("FILE") { + func_ = [default_path, enableErrorReturn](std::string &filename) { + auto path_result = detail::check_path(filename.c_str()); + if(path_result == detail::path_type::nonexistent) { + std::string test_file_path = default_path; + if(default_path.back() != '/' && default_path.back() != '\\') { + // Add folder separator + test_file_path += '/'; + } + test_file_path.append(filename); + path_result = detail::check_path(test_file_path.c_str()); + if(path_result == detail::path_type::file) { + filename = test_file_path; + } else { + if(enableErrorReturn) { + return "File does not exist: " + filename; + } + } + } + return std::string{}; + }; +} + +CLI11_INLINE AsSizeValue::AsSizeValue(bool kb_is_1000) : AsNumberWithUnit(get_mapping(kb_is_1000)) { + if(kb_is_1000) { + description("SIZE [b, kb(=1000b), kib(=1024b), ...]"); + } else { + description("SIZE [b, kb(=1024b), ...]"); + } +} + +CLI11_INLINE std::map AsSizeValue::init_mapping(bool kb_is_1000) { + std::map m; + result_t k_factor = kb_is_1000 ? 1000 : 1024; + result_t ki_factor = 1024; + result_t k = 1; + result_t ki = 1; + m["b"] = 1; + for(std::string p : {"k", "m", "g", "t", "p", "e"}) { + k *= k_factor; + ki *= ki_factor; + m[p] = k; + m[p + "b"] = k; + m[p + "i"] = ki; + m[p + "ib"] = ki; + } + return m; +} + +CLI11_INLINE std::map AsSizeValue::get_mapping(bool kb_is_1000) { + if(kb_is_1000) { + static auto m = init_mapping(true); + return m; + } + static auto m = init_mapping(false); + return m; +} + +namespace detail { + +CLI11_INLINE std::pair split_program_name(std::string commandline) { + // try to determine the programName + std::pair vals; + trim(commandline); + auto esp = commandline.find_first_of(' ', 1); + while(detail::check_path(commandline.substr(0, esp).c_str()) != path_type::file) { + esp = commandline.find_first_of(' ', esp + 1); + if(esp == std::string::npos) { + // if we have reached the end and haven't found a valid file just assume the first argument is the + // program name + if(commandline[0] == '"' || commandline[0] == '\'' || commandline[0] == '`') { + bool embeddedQuote = false; + auto keyChar = commandline[0]; + auto end = commandline.find_first_of(keyChar, 1); + while((end != std::string::npos) && (commandline[end - 1] == '\\')) { // deal with escaped quotes + end = commandline.find_first_of(keyChar, end + 1); + embeddedQuote = true; + } + if(end != std::string::npos) { + vals.first = commandline.substr(1, end - 1); + esp = end + 1; + if(embeddedQuote) { + vals.first = find_and_replace(vals.first, std::string("\\") + keyChar, std::string(1, keyChar)); + } + } else { + esp = commandline.find_first_of(' ', 1); + } + } else { + esp = commandline.find_first_of(' ', 1); + } + + break; + } + } + if(vals.first.empty()) { + vals.first = commandline.substr(0, esp); + rtrim(vals.first); + } + + // strip the program name + vals.second = (esp < commandline.length() - 1) ? commandline.substr(esp + 1) : std::string{}; + ltrim(vals.second); + return vals; +} + +} // namespace detail +/// @} + + + + +class Option; +class App; + +/// This enum signifies the type of help requested +/// +/// This is passed in by App; all user classes must accept this as +/// the second argument. + +enum class AppFormatMode { + Normal, ///< The normal, detailed help + All, ///< A fully expanded help + Sub, ///< Used when printed as part of expanded subcommand +}; + +/// This is the minimum requirements to run a formatter. +/// +/// A user can subclass this is if they do not care at all +/// about the structure in CLI::Formatter. +class FormatterBase { + protected: + /// @name Options + ///@{ + + /// The width of the first column + std::size_t column_width_{30}; + + /// @brief The required help printout labels (user changeable) + /// Values are Needs, Excludes, etc. + std::map labels_{}; + + ///@} + /// @name Basic + ///@{ + + public: + FormatterBase() = default; + FormatterBase(const FormatterBase &) = default; + FormatterBase(FormatterBase &&) = default; + FormatterBase &operator=(const FormatterBase &) = default; + FormatterBase &operator=(FormatterBase &&) = default; + + /// Adding a destructor in this form to work around bug in GCC 4.7 + virtual ~FormatterBase() noexcept {} // NOLINT(modernize-use-equals-default) + + /// This is the key method that puts together help + virtual std::string make_help(const App *, std::string, AppFormatMode) const = 0; + + ///@} + /// @name Setters + ///@{ + + /// Set the "REQUIRED" label + void label(std::string key, std::string val) { labels_[key] = val; } + + /// Set the column width + void column_width(std::size_t val) { column_width_ = val; } + + ///@} + /// @name Getters + ///@{ + + /// Get the current value of a name (REQUIRED, etc.) + CLI11_NODISCARD std::string get_label(std::string key) const { + if(labels_.find(key) == labels_.end()) + return key; + return labels_.at(key); + } + + /// Get the current column width + CLI11_NODISCARD std::size_t get_column_width() const { return column_width_; } + + ///@} +}; + +/// This is a specialty override for lambda functions +class FormatterLambda final : public FormatterBase { + using funct_t = std::function; + + /// The lambda to hold and run + funct_t lambda_; + + public: + /// Create a FormatterLambda with a lambda function + explicit FormatterLambda(funct_t funct) : lambda_(std::move(funct)) {} + + /// Adding a destructor (mostly to make GCC 4.7 happy) + ~FormatterLambda() noexcept override {} // NOLINT(modernize-use-equals-default) + + /// This will simply call the lambda function + std::string make_help(const App *app, std::string name, AppFormatMode mode) const override { + return lambda_(app, name, mode); + } +}; + +/// This is the default Formatter for CLI11. It pretty prints help output, and is broken into quite a few +/// overridable methods, to be highly customizable with minimal effort. +class Formatter : public FormatterBase { + public: + Formatter() = default; + Formatter(const Formatter &) = default; + Formatter(Formatter &&) = default; + Formatter &operator=(const Formatter &) = default; + Formatter &operator=(Formatter &&) = default; + + /// @name Overridables + ///@{ + + /// This prints out a group of options with title + /// + CLI11_NODISCARD virtual std::string + make_group(std::string group, bool is_positional, std::vector opts) const; + + /// This prints out just the positionals "group" + virtual std::string make_positionals(const App *app) const; + + /// This prints out all the groups of options + std::string make_groups(const App *app, AppFormatMode mode) const; + + /// This prints out all the subcommands + virtual std::string make_subcommands(const App *app, AppFormatMode mode) const; + + /// This prints out a subcommand + virtual std::string make_subcommand(const App *sub) const; + + /// This prints out a subcommand in help-all + virtual std::string make_expanded(const App *sub) const; + + /// This prints out all the groups of options + virtual std::string make_footer(const App *app) const; + + /// This displays the description line + virtual std::string make_description(const App *app) const; + + /// This displays the usage line + virtual std::string make_usage(const App *app, std::string name) const; + + /// This puts everything together + std::string make_help(const App * /*app*/, std::string, AppFormatMode) const override; + + ///@} + /// @name Options + ///@{ + + /// This prints out an option help line, either positional or optional form + virtual std::string make_option(const Option *opt, bool is_positional) const { + std::stringstream out; + detail::format_help( + out, make_option_name(opt, is_positional) + make_option_opts(opt), make_option_desc(opt), column_width_); + return out.str(); + } + + /// @brief This is the name part of an option, Default: left column + virtual std::string make_option_name(const Option *, bool) const; + + /// @brief This is the options part of the name, Default: combined into left column + virtual std::string make_option_opts(const Option *) const; + + /// @brief This is the description. Default: Right column, on new line if left column too large + virtual std::string make_option_desc(const Option *) const; + + /// @brief This is used to print the name on the USAGE line + virtual std::string make_option_usage(const Option *opt) const; + + ///@} +}; + + + + +using results_t = std::vector; +/// callback function definition +using callback_t = std::function; + +class Option; +class App; + +using Option_p = std::unique_ptr