New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Report some electricity usage in kW W or kWh in IP units options #10256
Conversation
…e style controls and sql unit conversions.
…or table style controls and sql unit conversions.
…rent branch, taking the upstream develop changes for now as the first step.
…nt branch; took both branch changes and then made some hand revisions.
… reporting for ip-electricity option.
@Myoldmopar @jcyuan2020 @Myoldmopar it has been 28 days since this pull request was last updated. |
@jcyuan2020 I pulled this branch and started resolving conflicts, but they became a little more than I was expecting. Could you take a pass at pulling develop in and resolving them? They will likely be super easy since you were the one making these changes. If you aren't able to, I'll give it another dedicated pass. Thanks! |
@Myoldmopar Sure. I am starting to get these resolved. |
… while merging in upstream develop branch. Went through each conflicted block to manually merge and or modify.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, so this is almost all good. I had two comments that you can respond to, either in reply, or code changes:
- I dislike the magic number 1 being used in the electricity detection. Do we not have a named variable that already points to the electricity resource type? I'd love to have that dynamically defined so that if we ever change the resource type numbers, it won't break that calculation.
- With the many repeated checks on
if (ip or ip_except_elec)
being added in ORT, I feel like it's worth doing it as nicely as possible. In this case, I do think a worker method would be a very nice touch. Let me know what you think.
@@ -7823,16 +7826,17 @@ void WriteBEPSTable(EnergyPlusData &state) | |||
|
|||
// convert units into GJ (divide by 1,000,000,000) if J otherwise kWh | |||
for (int iResource = 1; iResource <= 13; ++iResource) { // don't do water | |||
Real64 ipElectricityAdjust = (iResource == 1) ? ipElectricityConversionFactor : 1.0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, so here is where we are adjusting it for electricity or not. The iResource as 1 and 13 look.....funny. Is there really not a named enum we can use for (iResource == 1) ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do feel that using enums (or values converted from enum to int) should be the way to go in general. However I would also tread with caution for now, for two reasons. 1. from the original definition, it has a mix of number 14 and EndUse:Num (which is also 14). This means that there are some initial activities started on changing this to use enum already---but probably not complete for some reasons (probably due to the complexity in this piece of code?):
- There are some mapping which is not perfectly aligned for the index e.g. from 1 (electricity) ->1; 2->2, demonstrated in the following lines:
There you can observe that the index mapping from one vector (left) to that for the other vector (or multi-dim array/vector) is not completely aligned. There are 3->6; 4-8, and 5->9; and more. There are at least a few more blocks that look like this.
This in one hand probably does mean that using enum could be a better solution for some scenarios in this big file. But on the other hand, it also added complexity to go over the code to make sure at each these are done correctly for all of them.
Probably it would be an overall effort of refactoring the numbers like this in this file to enum. (I think @amir at some point also mentioned about this last year). I generally feel this undertake might be a separate refactoring pr or something like that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The EndUse::Num
stuff is from me, from the EndUse
refactor PR. I didn't do the entire file (which is enormous) only the loops that I actually changed.
Similarly, I am not suggesting you do this as part of this PR. This should probably be a separate effort.
But it should be an effort because new people are going to need to add to and modify this module and they will also need to learn what all of these numbers mean. It's bad coding practice to use numbers instead of enum
values, which have meaning that you don't have to look up. It's a form of self-documentation. Same reason for using meaningful names for variables and functions.
@@ -3354,7 +3345,7 @@ void WriteTableOfContents(EnergyPlusData &state) | |||
for (int jTable = 1; jTable <= ort->OutputTableBinned(iInput).numTables; ++jTable) { | |||
int const curTable = ort->OutputTableBinned(iInput).resIndex + (jTable - 1); | |||
std::string curName; | |||
if (ort->unitsStyle == UnitsStyle::InchPound) { | |||
if ((ort->unitsStyle == UnitsStyle::InchPound) || (ort->unitsStyle == UnitsStyle::InchPoundExceptElectricity)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This repeated pattern is probably fine. I'm inclined to say you could add a little worker method to the ort class to clean this code up. Consider this example:
#include <iostream>
enum class UnitsStyle {InchPound, InchPoundExceptElectricity, SI};
struct ORT {
UnitsStyle unitsStyle;
ORT(UnitsStyle us) : unitsStyle(us) {}
bool ip() const {
return this->unitsStyle == UnitsStyle::InchPound || this->unitsStyle == UnitsStyle::InchPoundExceptElectricity;
}
};
int main() {
ORT ort1(UnitsStyle::InchPound);
std::cout << ort1.ip() << std::endl;
ORT ort2(UnitsStyle::InchPoundExceptElectricity);
std::cout << ort2.ip() << std::endl;
ORT ort3(UnitsStyle::SI);
std::cout << ort3.ip() << std::endl;
}
That way all of these if checks would just be replaced with:
if (ort->ip()) {
Which is a lot less to digest. Notes:
- I didn't look up the actual ort struct name, that's just a quick example
- I'm not saying
ip
is really the right function name, just a quick guess
Do you think this change is worth it here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I got the idea here. Probably worth a try---except the "ORT" struct name could be a little bit confusing here as there are many similar names of "ort" or something alike that are already used in this(these) file(s).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ORT is just a dummy name I put in that sample code. Take the ort
variable...it is some type. Is it an instance of a struct OutputReportTabular
? If so, then my example is meant to add a method as such:
struct OutputReportTabular {
bool ip() const {
/// etc.
}
}
Basically - add the new method to whatever struct the ort
variable is.
" AND RowName = 'Heating'"); | ||
auto result = queryResult(query, "TabularDataWithStrings"); | ||
|
||
ASSERT_EQ(14u, result.size()) << "Failed for query: " << query; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some of this testing feels unrelated, but maybe I'm missing something. Anyway, it looks like at least some of the rates are being compared properly, so I'll take it.
unitsStyleReturn = UnitsStyle::InchPound; | ||
} else { | ||
UnitsStyle unitsStyleReturn = static_cast<UnitsStyle>(getEnumValue(UnitsStyleNamesUC, Util::makeUPPER(unitStringIn))); | ||
if (unitsStyleReturn == UnitsStyle::Invalid) { | ||
unitsStyleReturn = UnitsStyle::NotFound; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just replace uses of NotFound
with Invalid
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That could be from the legacy---NotFound
was the original way of dealing with blacks or something invalid before the enum
ear and here it was assigned to a higher value (than all valid entries). Then Invalid
becomes the standard values to be included in an enum
as -1. Probably it is time to revisit again to see--actually I do find a note three years ago (likely from me myself) about the use of NotFound
and seemed to have some reason to keep it at that time:
ort->gatherElecProduced /= largeConversionFactor; | ||
ort->gatherElecPurchased /= largeConversionFactor; | ||
ort->gatherElecSurplusSold /= largeConversionFactor; | ||
ort->gatherPowerFuelFireGen /= (largeConversionFactor / ipElectricityConversionFactor); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The compiler is going to do this for you anyway, but for readability you should probably define Real64 convFactor = ipElectricityConversionFactor / largeConversionFactor;
. At that point you could also multiply rather than divide which is both faster and higher bandwidth, i.e., the processor has more multipliers than dividers because multiplication is common and also each multiplier is faster than each divider.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! A good point to use multiplication whenever possible.
@@ -8426,6 +8438,22 @@ void WriteBEPSTable(EnergyPlusData &state) | |||
columnHead(13) = "District Heating Steam [kBtu]"; | |||
columnHead(14) = "Water [gal]"; | |||
} break; | |||
case UnitsStyle::InchPoundExceptElectricity: { | |||
columnHead(1) = "Electricity [kWh]"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to have to do something about this. Not today though.
collapsedEndUse(12, jEndUse) = ort->gatherDemandEndUse(4, jEndUse) * powerConversion; // district heating water | ||
collapsedEndUse(13, jEndUse) = ort->gatherDemandEndUse(5, jEndUse) * powerConversion; // district heating steam | ||
collapsedEndUse(14, jEndUse) = ort->gatherDemandEndUse(7, jEndUse) * flowConversion; // water | ||
collapsedEndUse(1, jEndUse) = ort->gatherDemandEndUse(1, jEndUse) * (powerConversion / ipElectricityConversion); // electricity |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need to fix this now but this 1, 2, 6, 8 business is not good. At all.
This isn't quite right. I'll fix it up in the morning. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything works locally, and the ip() function is fixed up. It could be enhanced further for the remaining locations, but that can certainly come later. If CI is happy with my last commit I think this can go right in.
{ | ||
return this->unitsStyle == OutputReportTabular::UnitsStyle::InchPound || | ||
this->unitsStyle == OutputReportTabular::UnitsStyle::InchPoundExceptElectricity; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jcyuan2020 this is what I meant. Add a member method to the existing ort-based structure, not adding a whole new struct.
@@ -5536,7 +5527,7 @@ void FillWeatherPredefinedEntries(EnergyPlusData &state) | |||
lnPtr = index(lineIn.substr(12), 'm'); | |||
if (lnPtr != std::string::npos) { | |||
curNameWithSIUnits = "Elevation (m) " + lineIn.substr(12 + lnPtr + 2); | |||
if (ort->unitsStyle == UnitsStyle::InchPound) { | |||
if (ort->ip()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is what I wanted it to look like.
@@ -7069,7 +7060,8 @@ void WriteMonthlyTables(EnergyPlusData &state) | |||
curAggString = " {" + stripped(curAggString) + '}'; | |||
} | |||
// do the unit conversions | |||
if (unitsStyle_cur == UnitsStyle::InchPound) { | |||
if (unitsStyle_cur == OutputReportTabular::UnitsStyle::InchPound || | |||
unitsStyle_cur == OutputReportTabular::UnitsStyle::InchPoundExceptElectricity) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keep in mind though, that the ip() function only checks the value of unitsStyle defined currently on the ORT state instance. So if you are comparing some other style, that function isn't the right one to use, so I just left these remaining ones as if(thisUnitsStyle == A || thisUnitsStlye == B)
Alright, merging this right in. Thanks @jcyuan2020 and all reviewers. |
Pull request overview
NOTE: ENHANCEMENTS MUST FOLLOW A SUBMISSION PROCESS INCLUDING A FEATURE PROPOSAL AND DESIGN DOCUMENT PRIOR TO SUBMITTING CODE
Pull Request Author
Add to this list or remove from it as applicable. This is a simple templated set of guidelines.
Reviewer
This will not be exhaustively relevant to every PR.