Skip to content
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

Absorption chillerheater plant loop fixes #8556

Merged

Conversation

jcyuan2020
Copy link
Contributor

@jcyuan2020 jcyuan2020 commented Feb 22, 2021

Pull request overview

Pull Request Author

Add to this list or remove from it as applicable. This is a simple templated set of guidelines.

  • 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

This will not be exhaustively relevant to every PR.

  • 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

@jcyuan2020 jcyuan2020 force-pushed the I8554_I8555_chillerheater_plant_loop_fixes branch from 8fed19b to e404dfb Compare February 24, 2021 04:39
@mjwitte mjwitte added the Defect Includes code to repair a defect in EnergyPlus label Feb 26, 2021
@mjwitte mjwitte added this to the EnergyPlus 9.5.0 milestone Feb 26, 2021
@jcyuan2020 jcyuan2020 force-pushed the I8554_I8555_chillerheater_plant_loop_fixes branch from 6814516 to 1d49d51 Compare February 26, 2021 19:29
@jcyuan2020 jcyuan2020 marked this pull request as ready for review March 1, 2021 17:39
@mjwitte mjwitte requested a review from Myoldmopar March 1, 2021 17:50
@jcyuan2020 jcyuan2020 force-pushed the I8554_I8555_chillerheater_plant_loop_fixes branch from bad52a7 to c3940d6 Compare March 1, 2021 20:33
.LoopSide(calledFromLocation.loopSideNum)
.Branch(calledFromLocation.branchNum)
.TotalComponents;

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The revised code will check all components in a branch, rather than just checking the branch head element as before.

.Branch(calledFromLocation.branchNum)
.Comp(iComp)
.NodeNumIn;

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Still using the `hacky' way, but applied to all the components in the loop branch.

} else {
matchfound = false;
}
}
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 match found, update the loads values accordingly, break and return. Otherwise, continue to the next component check.

.Branch(calledFromLocation.branchNum)
.TotalComponents;

for (int iComp = 1; iComp <= branchTotalComp; iComp++) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The revised code checks all the elements in an (exhaust or gas-fired) absorption chiller heat plant loop branch, to identity which (chilled water, hot water, or condensing water) branch it is simulating. This is in contrast to the original code where only head branch component is checked.

} else {
brIdentity = 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.

Use an integer number (brIndentity) to identify the loop branch property: 1 for chilled water; 2 for hot water; 3 for condensing water; 0 indicates problem (no match).

Copy link
Member

Choose a reason for hiding this comment

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

This is kinda odd. If it is just an identifier and the value doesn't matter, this should be an enum class. I would like to see that changed before this is merged. I can make the change if needed, just let me know.

Copy link
Member

Choose a reason for hiding this comment

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

Much nicer than the magic numbers, thank you!


// Match inlet node name of calling branch to determine if this call is for heating or cooling
if (BranchInletNodeNum == this->ChillReturnNodeNum) { // Operate as chiller
if (brIdentity == 1) {
this->InCoolingMode = RunFlag != 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.

After the current branch is identified, run the corresponding functions/code blocks to execute the simulation. Slightly reorganized from the original code.

@@ -131,23 +131,47 @@ namespace EnergyPlus::ChillerExhaustAbsorption {

void ExhaustAbsorberSpecs::simulate(EnergyPlusData &state, const PlantLocation &calledFromLocation, bool FirstHVACIteration, Real64 &CurLoad, bool RunFlag)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The changes are applied to both the Exhaust fired absorption chiller heater, and the gas fired absorption chiller heater. For each types of absorption chiller heater, the getDesignCapacities() and the simulate() functions would be check to identity the loop/branch type (chilled water, hot water, or condenser water).

@@ -1626,7 +1672,7 @@ namespace EnergyPlus::ChillerExhaustAbsorption {
} else {
ShowSevereError(state, "CalcExhaustAbsorberChillerModel: Condenser flow = 0, for Exhaust Absorber Chiller=" + this->Name);
ShowContinueErrorTimeStamp(state, "");
ShowFatalError(state, "Program Terminates due to previous error condition.");
// ShowFatalError(state, "Program Terminates due to previous error condition.");
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 do not show the fatal message and terminate any more--this is aligned with the kind of common treatment used in other type of chiller (electric or absorption) models.

Copy link
Member

Choose a reason for hiding this comment

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

Hmmm.... OK, so if we show a severe then we need to fatal. If we aren't going to fatal then this needs to be a warning. But if it's a warning that could occur multiple times should we do a recurring warning message to avoid huge error files?

Copy link
Member

@Myoldmopar Myoldmopar left a comment

Choose a reason for hiding this comment

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

I think we should fix the magic numbers and make them an enum. If you aren't able to make that change, I can do it, just let me know.

} else {
brIdentity = 0;
}
}
Copy link
Member

Choose a reason for hiding this comment

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

This is kinda odd. If it is just an identifier and the value doesn't matter, this should be an enum class. I would like to see that changed before this is merged. I can make the change if needed, just let me know.

@jcyuan2020
Copy link
Contributor Author

I think we should fix the magic numbers and make them an enum. If you aren't able to make that change, I can do it, just let me know.

Thanks! Updating it. Will test and push again.

CONDENSER,
NOMATCH
};
brLoopType brIdentity(NOMATCH);
Copy link
Member

@Myoldmopar Myoldmopar Mar 5, 2021

Choose a reason for hiding this comment

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

This is much closer, but not quite there. I'm confused why this enum is repeated in the two cases. It should be declared once. Please:

  • move this one enum declaration to either the top of the ChillerExhaustAbsorption.cc file, or in the header,
  • make it an enum class instead of a raw enum,
  • change the enum name from camelCase to PascalCase,
  • change the member names from SCREAMINGCASE to PascalCase,
  • and make the accompanying change for the enum class by using the namespace below (BrLoopType::Chiller)

Copy link
Contributor Author

@jcyuan2020 jcyuan2020 Mar 5, 2021

Choose a reason for hiding this comment

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

This is much closer, but not quite there. I'm confused why this enum is repeated in the two cases. It should be declared once. Please:

* move this one enum declaration to either the top of the ChillerExhaustAbsorption.cc file, or in the header,

* make it an `enum class` instead of a raw `enum`,

* change the enum name from `camelCase` to `PascalCase`,

* change the member names from `SCREAMINGCASE` to `PascalCase`,

* and make the accompanying change for the `enum class` by using the namespace below (`BrLoopType::Chiller`)

I will make the changes. For why it was done twice in the two functions: actually these variables are very "local" to the simulate() functions so I did not want to bump up their scope.
It might be a little bit debatable since it is just a type definition. Or we can make the scope an even higher level up, so that both the ChillerExhaustAbsorption.cc (or hh) and the ChillerGasAbsorption.cc (or .hh) can see the definition.

Any comments or thoughts?

Copy link
Member

Choose a reason for hiding this comment

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

Wherever it makes sense is fine with me. But duplicating the same list of enumarations in two places smells like it needs to be DRYd up. For now, I say just move it up to the file level here so it can be shared between these two functions without duplication.

And you are correct about the type declaration comment, the scope here doesn't matter since an enum is just optimized away quickly, so it won't affect runtime. The scope should simply be determined by how many components this can be applied to.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So putting the definition in EnergyPlus/Plant/Enum.hh seems to be a good choice; then add #inlcude<EnergyPlus/Plant/Enum.hh> to both ChillerExhaustAbsorption.cc and ChillerGasAbsorption.cc.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Or definition in EnergyPlus/Plant/DataPlant.hh, which is already included in both both ChillerExhaustAbsorption.cc and ChillerGasAbsorption.cc.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

See the new commits.

Copy link
Member

@Myoldmopar Myoldmopar left a comment

Choose a reason for hiding this comment

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

OK, I need one more reply back about the severe/warning/recurring comment. I actually do think it's worth changing to at least a warning message, but I'm curious about the recurring change as well. @jcyuan2020 what do you think? Would this warning end up coming out in the error file many many times? Or just once? If it's just a one time sort of message then a regular warning is fine, and I can quickly make that change and get this merged. If it needs to be a recurring message I may just push this back for that one more change from you.

Or, I could have totally missed something and you can correct me.

Thanks for this effort, either way this is very nearly done.

} else {
brIdentity = 0;
}
}
Copy link
Member

Choose a reason for hiding this comment

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

Much nicer than the magic numbers, thank you!

@@ -1626,7 +1672,7 @@ namespace EnergyPlus::ChillerExhaustAbsorption {
} else {
ShowSevereError(state, "CalcExhaustAbsorberChillerModel: Condenser flow = 0, for Exhaust Absorber Chiller=" + this->Name);
ShowContinueErrorTimeStamp(state, "");
ShowFatalError(state, "Program Terminates due to previous error condition.");
// ShowFatalError(state, "Program Terminates due to previous error condition.");
Copy link
Member

Choose a reason for hiding this comment

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

Hmmm.... OK, so if we show a severe then we need to fatal. If we aren't going to fatal then this needs to be a warning. But if it's a warning that could occur multiple times should we do a recurring warning message to avoid huge error files?

Heater,
Condenser,
NoMatch
};
Copy link
Member

Choose a reason for hiding this comment

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

Yup, great! In a future set of changes the actual type name might be tailored a little more to the actual application, but this is fine for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Myoldmopar Thanks! Yes, the warnings are usually recurring. So it makes sense to condense them.

@Myoldmopar
Copy link
Member

My concern was still not fully addressed. It looks to be like we have a ShowSevereError that now no longer fatals. That is an invalid pattern -- even though yes there may still be a few of them lurking in the code. If it is a severe error, then it requires a fatal. If it is not going to fatal then it needs to be a warning.

I suspect it needs to be a warning.

Now, if it is a warning, it could occur many times in the course of a single simulation. We don't want our error files to be thousands of lines long, so we need to instead use the ShowRecurringWarning style error messages so that we only print the first one plus a summary at the end.

Right now I think a user could end up with dozens? thousands?? of severe errors in their error file, when it should've just been a recurring warning.

I don't think this is quite ready.

@jcyuan2020
Copy link
Contributor Author

jcyuan2020 commented Mar 20, 2021

My concern was still not fully addressed. It looks to be like we have a ShowSevereError that now no longer fatals. That is an invalid pattern -- even though yes there may still be a few of them lurking in the code. If it is a severe error, then it requires a fatal. If it is not going to fatal then it needs to be a warning.

I suspect it needs to be a warning.

Now, if it is a warning, it could occur many times in the course of a single simulation. We don't want our error files to be thousands of lines long, so we need to instead use the ShowRecurringWarning style error messages so that we only print the first one plus a summary at the end.

Right now I think a user could end up with dozens? thousands?? of severe errors in their error file, when it should've just been a recurring warning.

I don't think this is quite ready.

Thanks for the comments! I thought the original question was whether this would be a recurring warning, and my answer was that these warnings could indeed be recurring:
See here #8556 (comment)

As to whether the severe warnings should report fatal, currently this change is trying to make it similar to the way how other chiller and regular absorption chiller models handle such a stiuation---I think for those chiller models, it would be just report severe error but does not fatal out on it.

So for the recurrent ones, do you want me change it to using the recurrent errors mode? I can make that change for the two absorption chillerheater models involved in this PR.

BTW, if related, I think for the other chiller models (e.g. electric or regular absorption), the use of recurrent ones had not propagated in yet.

@Myoldmopar
Copy link
Member

@jcyuan2020 thanks for the further details. I'm not excited about dropping this in with the severe-no-fatal and non-recurring errors, but indeed this is happening with the other objects, so this is not a widespread issue. Given our timing I think I will merge this in after I finish testing it locally.

@Myoldmopar
Copy link
Member

This passes fine locally with develop pulled in. I'll merge it now. @jcyuan2020 please open an issue to address after the release where the severe-no-fatal code paths are cleaned up in relevant objects and also the messages should become recurring. Thanks!

@jcyuan2020
Copy link
Contributor Author

@Myoldmopar Thanks! The issue has been posted---Issue #8638

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Defect Includes code to repair a defect in EnergyPlus
Projects
None yet
8 participants