Skip to content

Conversation

@Nigusse
Copy link
Contributor

@Nigusse Nigusse commented Mar 5, 2025

Pull request overview

  • New Feature:
  • Modifies Ideal Loads Air System model to report fuel energy consumptions using use specified fuel conversion efficiency values. The efficiency value or values are specified as a schedule value.
  • Adds Heating and Cooling Fuel Efficiency Fields. The efficiency values are used to convert loads into fuel energy consumptions.
  • Users can specify the heating and cooling fuel types for reporting to tabular outputs of energy end-uses by fuel type.

Description of the purpose of this PR

Pull Request Author

  • Title of PR should be user-synopsis style (clearly understandable in a standalone changelog context)
  • Label the PR with at least one of: Defect, Refactoring, NewFeature, Performance, and/or DoNoPublish
  • Pull requests that impact EnergyPlus code must also include unit tests to cover enhancement or defect repair
  • Author should provide a "walkthrough" of relevant code changes using a GitHub code review comment process
  • If any diffs are expected, author must demonstrate they are justified using plots and descriptions
  • If changes fix a defect, the fix should be demonstrated in plots and descriptions
  • If any defect files are updated to a more recent version, upload new versions here or on DevSupport
  • If IDD requires transition, transition source, rules, ExpandObjects, and IDFs must be updated, and add IDDChange label
  • If structural output changes, add to output rules file and add OutputChange label
  • If adding/removing any LaTeX docs or figures, update that document's CMakeLists file dependencies

Reviewer

  • Perform a Code Review on GitHub
  • If branch is behind develop, merge develop and build locally to check for side effects of the merge
  • If defect, verify by running develop branch and reproducing defect, then running PR and reproducing fix
  • If feature, test running new feature, try creative ways to break it
  • CI status: all green or justified
  • Check that performance is not impacted (CI Linux results include performance check)
  • Run Unit Test(s) locally
  • Check any new function arguments for performance impacts
  • Verify IDF naming conventions and styles, memos and notes and defaults
  • If new idf included, locally check the err file and other outputs

@Nigusse Nigusse added the NewFeature Includes code to add a new feature to EnergyPlus label Mar 5, 2025
Comment on lines 64 to 65
{Fuel_Eff_{cool}} = Cooling Fuel Efficiency, [-]
{Fuel_Eff_{heat}} = Heating Fuel Efficiency, [-]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you made these fields schedules, then you could have both inputs and the ability to use EMS actuators.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shorowit Good point. Your idea is to use the existing schedule actuators if needed to override the efficiency values in the schedule specified.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I support using schedule inputs here as well. And it's easy enough to add a Schedule:Constant if it's a fixed value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now, implemented using a schedule object for both cooling and heating fuel efficiency input fields.

@nrel-bot-2c
Copy link

@Nigusse @Myoldmopar it has been 28 days since this pull request was last updated.

@Nigusse
Copy link
Contributor Author

Nigusse commented Apr 30, 2025

@Myoldmopar I will start changing the Ideal Air Load System module's GetInput() function to JSON format. Please let me know if you have any concerns or if you want me to delay it. Thanks.

@github-actions
Copy link

github-actions bot commented May 2, 2025

⚠️ Regressions detected on macos-14 for commit e1d6c13

Regression Summary
  • EIO: 49
  • ESO Big Diffs: 25
  • MTR Big Diffs: 15
  • Table Big Diffs: 42
  • Table String Diffs: 21
  • ESO Small Diffs: 27
  • BND: 4
  • MTD: 4
  • Table Small Diffs: 3
  • MTR Small Diffs: 9
  • ERR: 1

@github-actions
Copy link

github-actions bot commented May 2, 2025

⚠️ Regressions detected on macos-14 for commit f755088

Regression Summary
  • BND: 4
  • MTD: 4
  • EIO: 1
  • ESO Big Diffs: 1
  • MTR Big Diffs: 1
  • Table Big Diffs: 1
  • Table String Diffs: 1

@github-actions
Copy link

github-actions bot commented May 5, 2025

⚠️ Regressions detected on macos-14 for commit bbea19a

Regression Summary
  • BND: 4
  • MTD: 4

Copy link
Contributor Author

@Nigusse Nigusse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary Of Changes:

  • Updated the IDD by adding new input fields for cooling and heating fuel efficiency schedule name
  • Transitioned GetInput() to use the JSON IDD
  • Modified the GetInput() for the two new input fields
  • Fuel energy consumption calculations for the new report variables

(6) * Zone Ideal Loads Supply Air Total Cooling Fuel Energy Rate [W] *
(7) * Zone Ideal Loads Supply Air Total Heating Fuel Energy [J] *
(8) * Zone Ideal Loads Supply Air Total Cooling Fuel Energy [J] *
```
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementation and Design Document

\note ideal air loads into fuel energy consumption.
\note The minimum schedule value must be greater than 0.0. The maximum value
\note depends on the technology, and can exceed 1.0.
\note If blank, cooling fuel efficiency value is always 1.0.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added Heating and Cooling Fuel Efficiency Schedule Name new input fields.

int CoolErrIndex; // Cooling setpoint error index (recurring errors)
int HeatErrIndex; // Heating setpoint error index (recurring errors)
Sched::Schedule *heatFuelEffSched = nullptr; // heating feul efficiency schedule
Sched::Schedule *coolFuelEffSched = nullptr; // cooling feul efficiency schedule
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pointer member variables for accessing the respective fuel efficiency schedule names.

Real64 TotHeatFuelRate; // Total heating fuel consumption rate [W]
Real64 TotCoolFuelRate; // Total cooling fuel consumption rate [W]
Real64 TotHeatFuelEnergy; // Total heating fuel consumption [J]
Real64 TotCoolFuelEnergy; // Total cooling fuel consumption [J]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added eight member report variables.

SupplyTemp(0.0), SupplyHumRat(0.0), MixedAirTemp(0.0), MixedAirHumRat(0.0)
SupplyTemp(0.0), SupplyHumRat(0.0), MixedAirTemp(0.0), MixedAirHumRat(0.0), ZoneTotHeatFuelRate(0.0), ZoneTotCoolFuelRate(0.0),
ZoneTotHeatFuelEnergy(0.0), ZoneTotCoolFuelEnergy(0.0), TotHeatFuelRate(0.0), TotCoolFuelRate(0.0), TotHeatFuelEnergy(0.0),
TotCoolFuelEnergy(0.0)
Copy link
Contributor Author

@Nigusse Nigusse May 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initialized the new member report variables added.

PurchAir.ZoneTotCoolFuelEnergy,
OutputProcessor::TimeStepType::System,
OutputProcessor::StoreType::Sum,
PurchAir.Name);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added two energy consumption report variables for zones: Zone Ideal Loads Zone Heating Fuel Energy and Zone Ideal Loads Cooling Fuel Energy.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added two energy consumption report variables for zones: Zone Ideal Loads Zone Heating Fuel Energy and Zone Ideal Loads Cooling Fuel Energy.

How do these differ from "Zone Ideal Loads Supply Air Total Heating Fuel Energy"?

PurchAir.TotCoolFuelRate,
OutputProcessor::TimeStepType::System,
OutputProcessor::StoreType::Average,
PurchAir.Name);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added two energy consumption rate report variables for supply air: Zone Ideal Loads Supply Air Total Heating Fuel Energy Rate and Zone Ideal Loads Supply Air Total Cooling Fuel Energy Rate.

PurchAir.ZoneTotCoolFuelRate,
OutputProcessor::TimeStepType::System,
OutputProcessor::StoreType::Average,
PurchAir.Name);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added two energy consumption rate report variables for zones: Zone Ideal Loads Zone Heating Fuel Energy Rate and Zone Ideal Loads Zone Cooling Fuel Energy Rate.

Real64 coolFuelEffValue = PurchAir.heatFuelEffSched->getCurrentVal();
PurchAir.ZoneTotCoolFuelRate = PurchAir.ZoneTotCoolRate / coolFuelEffValue;
PurchAir.TotCoolFuelRate = PurchAir.TotCoolRate / coolFuelEffValue;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calculates Fuel Energy Rates from the Load and user-specified fuel efficiency values.

PurchAir.ZoneTotHeatFuelEnergy = PurchAir.ZoneTotHeatFuelRate * TimeStepSysSec;
PurchAir.ZoneTotCoolFuelEnergy = PurchAir.ZoneTotCoolFuelRate * TimeStepSysSec;
PurchAir.TotHeatFuelEnergy = PurchAir.TotHeatFuelRate * TimeStepSysSec;
PurchAir.TotCoolFuelEnergy = PurchAir.TotCoolFuelRate * TimeStepSysSec;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calculates Fuel Energy consumption from Fuel Consumption rates and elapsed time.

s_ipsc->lNumericFieldBlanks,
s_ipsc->lAlphaFieldBlanks,
s_ipsc->cAlphaFieldNames,
s_ipsc->cNumericFieldNames);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getObjectItem isn't used for json processing

state.dataPurchasedAirMgr->PurchAirNumericFields(purchAirNum).FieldNames = s_ipsc->cNumericFieldNames;
Util::IsNameEmpty(state, thisObjectName, s_ipsc->cCurrentModuleObject, ErrorsFound);
PurchAir.Name = Util::makeUPPER(thisObjectName);
cAlphaFieldName = "Availability Schedule Name";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you need this string but am now wondering how CheckUniqueNodeNames (line 312) handles json field name?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I considered it during implementation, but I couldn't find a way to do it without saving the field names here. We use these field names in the sizing calculation. See example below:

SizingString = state.dataPurchasedAirMgr->PurchAirNumericFields(PurchAirNum).FieldNames(FieldNum) + " [m3/s]";

ShowSevereInvalidKey(state, eoh, cAlphaFieldName, fieldValue, "Valid entries are None, FlowRate, Capacity, or FlowRateAndCapacity.");
ErrorsFound = true;
} break;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code, lines 369 - 407, is not needed since this field has a default (i.e., this field will not be blank) and the enum was set at line 368. Same comment for Cooling Limit below.

A6 , \field Heating Limit
   \type choice
   \key NoLimit
   \key LimitFlowRate
   \key LimitCapacity
   \key LimitFlowRateAndCapacity
   \default NoLimit

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, maybe you do need this code. There is some trickery that resets the Heating Limit based on other inputs. Leave this code as-is.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I take that back. The fields being checked here have \default autosizable so none of the checks will == fields.end(). This code is redundant.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are additional checks required, which could change the limit value. But these fields will not be blank since they have a default value. I will comment out the code and check if it breaks any of the unit tests.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each one of these checks use else if (fields.find("something") == fields.end()). Those will never happen because those fields default to autosize if blank so the code drops to the else and gives the same enum as the case statement.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

fieldValue,
"Valid entries are ConstantSensibleHeatRatio, Humidistat, or ConstantSupplyHumidityRatio.");
ErrorsFound = true;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not possible for PurchAir.DehumidCtrlType == HumControl::Invalid since there is a default for this field. This code will never execute. Delete lines 477 - 484. Same for Humidification Control Type lines 490 - 493.

"To activate CO2 simulation, use ZoneAirContaminantBalance object and specify \"Carbon Dioxide "
"Concentration\"=\"Yes\".");
}
} else if (PurchAir.DCVType == DCV::Invalid) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This else if is not possible since there is a default. The else if can be deleted (it will never execute).

A14, \field Demand Controlled Ventilation Type
   \key None
   \key OccupancySchedule
   \key CO2Setpoint
   \default None

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor

@rraustad rraustad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Final comments. The rest looks good.

cAlphaFieldName = "Outdoor Air Economizer Type";
fieldValue = s_ip->getAlphaFieldValue(fields, schemaProps, "outdoor_air_economizer_type");
PurchAir.EconomizerType = static_cast<Econ>(getEnumValue(econNamesUC, Util::makeUPPER(fieldValue)));
if (PurchAir.EconomizerType == Econ::Invalid) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not possible, delete.

A15, \field Outdoor Air Economizer Type
   \type choice
   \key NoEconomizer
   \key DifferentialDryBulb
   \key DifferentialEnthalpy
   \default NoEconomizer

cAlphaFieldName = "Heat Recovery Type";
fieldValue = s_ip->getAlphaFieldValue(fields, schemaProps, "heat_recovery_type");
PurchAir.HtRecType = static_cast<HeatRecovery>(getEnumValue(heatRecoveryNamesUC, Util::makeUPPER(fieldValue)));
if (PurchAir.HtRecType == HeatRecovery::Invalid) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not possible.

A16, \field Heat Recovery Type
   \type choice
   \key None
   \key Sensible
   \key Enthalpy
   \default None

cAlphaFieldName = "Cooling Fuel Type";
fieldValue = s_ip->getAlphaFieldValue(fields, schemaProps, "cooling_fuel_type");
PurchAir.coolingFuelType = static_cast<Constant::eFuel>(getEnumValue(Constant::eFuelNamesUC, Util::makeUPPER(fieldValue)));
if (PurchAir.coolingFuelType == Constant::eFuel::Invalid) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Invalid is not possible. This code will never execute. Delete.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the value in this field is invalid, it will be captured before it reaches this point. Is that what makes these lines of code redundant?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. The input processor will stop the simulation before reaching this point.

Constant::eResource::DistrictHeatingWater,
OutputProcessor::Group::HVAC,
OutputProcessor::EndUseCat::Heating);
PurchAir.Name);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But this is heating energy, not fuel energy. So this should have been left here? @mjwitte ?

PurchAir.SenHeatRate = max(PurchAir.SenCoilLoad, 0.0);
PurchAir.SenCoolRate = std::abs(min(PurchAir.SenCoilLoad, 0.0));
PurchAir.LatHeatRate = max(PurchAir.LatCoilLoad, 0.0);
PurchAir.LatCoolRate = std::abs(min(PurchAir.LatCoilLoad, 0.0));
PurchAir.TotHeatRate = PurchAir.SenHeatRate + PurchAir.LatHeatRate;
PurchAir.TotCoolRate = PurchAir.SenCoolRate + PurchAir.LatCoolRate;

PurchAir.ZoneSenHeatRate = max(PurchAir.SenOutputToZone, 0.0);
PurchAir.ZoneSenCoolRate = std::abs(min(PurchAir.SenOutputToZone, 0.0));
PurchAir.ZoneLatHeatRate = max(PurchAir.LatOutputToZone, 0.0);
PurchAir.ZoneLatCoolRate = std::abs(min(PurchAir.LatOutputToZone, 0.0));
PurchAir.ZoneTotHeatRate = PurchAir.ZoneSenHeatRate + PurchAir.ZoneLatHeatRate;
PurchAir.ZoneTotCoolRate = PurchAir.ZoneSenCoolRate + PurchAir.ZoneLatCoolRate;


Append an optional new field A21 which is also F32, "Cooling Fuel Type", defaulted to blank

See pull request [#10971] https://github.com/NREL/EnergyPlus/pull/10971
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to include this in transition rules since Heating/Cooling Fuel Type has a default and efficiency schedule defaults to AlwaysOn.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we had to always required to provide a transition rule for new fields. Is this because these new fields have default values and are appended at the end? Note that these new fields are outside the "min-field" range.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

min-fields does not mean what it did in the past. Defaults now get filled even when past min-fields. Adding blank fields at the end of an object will not provide any benefit except that the user will now see those fields in the input file. For that reason maybe it's OK to leave this as-is but that just means extra work for the transition program (albeit just a little bit of work).

@Nigusse
Copy link
Contributor Author

Nigusse commented Sep 25, 2025

"But this is heating energy, not fuel energy. So this should have been left here? @mjwitte ?"

@rraustad I did not change any of the existing variables; I added eight new report variables.

@Nigusse
Copy link
Contributor Author

Nigusse commented Sep 25, 2025

I removed several lines of unnecessary code that check for invalid inputs in fields with default values. By the time the code reaches the get input stage, any invalid values have already been addressed by the input processor. Therefore, there is no need to verify the value of a choice field that has a default value at the get input.

@mjwitte mjwitte added the IDDChange Code changes impact the IDD file (cannot be merged after IO freeze) label Sep 25, 2025
@mjwitte mjwitte added this to the EnergyPlus 25.2 IO Freeze milestone Sep 25, 2025
\begin{itemize}
\item {E_heat} = total heating fuel energy comsumption rate (W)
\item {E_cool} = total cooling fuel energy comsumption rate (W)
\item {\dot Q_load_heat} = zone total heating load (W)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These warnings must mean something because building the doc shows some weird formatting. Lines 139 and 140 above are on the same line in the pdf. And the equation definitions are also strange.

image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will look into it. @rraustad Thanks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed the equation format issues and tested it locally. Now, the equations and variable definitions are rendered correctly.

@github-actions
Copy link

⚠️ Regressions detected on macos-14 for commit f8ed9e9

Regression Summary
  • Audit: 76
  • MTD: 76
  • RDD: 73
  • BND: 4

@github-actions
Copy link

⚠️ Regressions detected on ubuntu-24.04 for commit f8ed9e9

Regression Summary
  • Audit: 78
  • MTD: 78
  • RDD: 75
  • BND: 4

@github-actions
Copy link

⚠️ Regressions detected on macos-14 for commit 20b5a51

Regression Summary
  • Audit: 76
  • MTD: 76
  • RDD: 73
  • BND: 4

@github-actions
Copy link

⚠️ Regressions detected on ubuntu-24.04 for commit 20b5a51

Regression Summary
  • Audit: 78
  • MTD: 78
  • RDD: 75
  • BND: 4

@github-actions
Copy link

⚠️ Regressions detected on macos-14 for commit 35ba05f

Regression Summary
  • Audit: 76
  • MTD: 76
  • RDD: 73
  • BND: 4

@github-actions
Copy link

⚠️ Regressions detected on ubuntu-24.04 for commit 35ba05f

Regression Summary
  • Audit: 78
  • MTD: 78
  • RDD: 75
  • BND: 4

@mitchute
Copy link
Collaborator

@rraustad @Nigusse anything else here? I've confirmed the doc issues were addressed.

@mitchute
Copy link
Collaborator

OK, hearing nothing further, I'm calling this one. Merging.

@mitchute mitchute merged commit b62ff20 into develop Sep 29, 2025
11 checks passed
@mitchute mitchute deleted the IdealLoadsAirSystem-FuelEfficiency branch September 29, 2025 17:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

IDDChange Code changes impact the IDD file (cannot be merged after IO freeze) NewFeature Includes code to add a new feature to EnergyPlus

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants