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

Fix #10817 - Avoid crash in FluidCooler/EvaporativeFluidCooler when Water flow rate autosized and no Sizing:Plant #10855

Open
wants to merge 11 commits into
base: develop
Choose a base branch
from

Conversation

jmarrec
Copy link
Contributor

@jmarrec jmarrec commented Dec 13, 2024

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

@jmarrec jmarrec added Defect Includes code to repair a defect in EnergyPlus NotIDDChange Code does not impact IDD (can be merged after IO freeze) labels Dec 13, 2024
@jmarrec jmarrec self-assigned this Dec 13, 2024
Copy link
Contributor Author

@jmarrec jmarrec left a comment

Choose a reason for hiding this comment

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

I have noticed more problems, but they will likely result in diffs in results so I didn't had them right now, as I'd like CI to report green.

@@ -356,10 +356,10 @@ TEST_F(EnergyPlusFixture, SizeFunctionTestWhenPlantSizingIndexIsZero)
auto &thisFluidCooler = state->dataFluidCoolers->SimpleFluidCooler(FluidCoolerNum);

state->dataPlnt->PlantLoop.allocate(FluidCoolerNum);
state->dataFluidCoolers->SimpleFluidCooler.allocate(FluidCoolerNum);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fix an existing test. When I tried to reuse it, I realized that the allocate after GetInput was resetting it to an empty (invalid / default initialized) FluidCooler

state->dataFluidCoolers->SimpleFluidCooler(FluidCoolerNum).plantLoc.loopNum = 1;
state->dataPlnt->PlantLoop(FluidCoolerNum).PlantSizNum = 0;

EXPECT_EQ("DRY COOLER", thisFluidCooler.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.

This would fail, before

@@ -389,10 +389,10 @@ TEST_F(EnergyPlusFixture, ExerciseSingleSpeedFluidCooler)

FluidCoolerspecs *ptr = FluidCoolerspecs::factory(*state, DataPlant::PlantEquipmentType::FluidCooler_SingleSpd, "DRY COOLER");

PlantLocation pl{1, EnergyPlus::DataPlant::LoopSideLocation::Demand, 1, 1};
PlantLocation pl{1, EnergyPlus::DataPlant::LoopSideLocation::Supply, 1, 1};
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unrelated, but place the fluid coolers on the supply side of the plant loop.

This makes no difference in test results, but it was bothering me that all of the FluidCooler.unit.cc / EvaporativeFluidCooler.unit.cc had the fluid coolers on the demand side

Comment on lines +512 to +551
TEST_F(EnergyPlusFixture, FluidCooler_SizeWhenPlantSizingIndexIsZeroAndAutosized)
{
// Test for #10817
std::string const idf_objects = delimited_string({
" FluidCooler:SingleSpeed,",
" Dry Cooler, !- Name",
" Dry Cooler Inlet Node, !- Water Inlet Node Name",
" Dry Cooler Outlet Node, !- Water Outlet Node Name",
" NominalCapacity, !- Performance Input Method",
" Autosize, !- Design Air Flow Rate U-factor Times Area Value {W/K}",
" 58601, !- Nominal Capacity {W}",
" 50, !- Design Entering Water Temperature {C}",
" 35, !- Design Entering Air Temperature {C}",
" 25, !- Design Entering Air Wetbulb Temperature {C}",
" Autosize, !- Design Water Flow Rate {m3/s}",
" Autosize, !- Design Air Flow Rate {m3/s}",
" Autosize; !- Design Air Flow Rate Fan Power {W}",
});

ASSERT_TRUE(process_idf(idf_objects));

GetFluidCoolerInput(*state);
int FluidCoolerNum(1);

state->dataPlnt->PlantLoop.allocate(FluidCoolerNum);
state->dataPlnt->PlantLoop(FluidCoolerNum).PlantSizNum = 0;

auto &thisFluidCooler = state->dataFluidCoolers->SimpleFluidCooler(FluidCoolerNum);
thisFluidCooler.plantLoc.loopNum = 1;

// Necessary to trigger the crash from #
state->dataPlnt->PlantFirstSizesOkayToFinalize = false;

EXPECT_TRUE(thisFluidCooler.DesignWaterFlowRateWasAutoSized);
EXPECT_TRUE(thisFluidCooler.HighSpeedFanPowerWasAutoSized);
EXPECT_TRUE(thisFluidCooler.HighSpeedAirFlowRateWasAutoSized);
EXPECT_TRUE(thisFluidCooler.HighSpeedFluidCoolerUAWasAutoSized);

thisFluidCooler.size(*state);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

New test, crashes before fix

Comment on lines +309 to +350
TEST_F(EnergyPlusFixture, EvapFluidCooler_SizeWhenPlantSizingIndexIsZeroAndAutosized)
{
// Test for #10817
std::string const idf_objects = delimited_string({
"EvaporativeFluidcooler:SingleSpeed,",
" Big EvaporativeFluidCooler, !- Name",
" Condenser EvaporativeFluidcooler Inlet Node, !- Water Inlet Node Name",
" Condenser EvaporativeFluidcooler Outlet Node, !- Water Outlet Node Name",
" Autosize, !- Design Air Flow Rate {m3/s}",
" Autosize, !- Design Air Flow Rate Fan Power {W}",
" 0.002208, !- Design Spray Water Flow Rate {m3/s}",
" UFactorTimesAreaAndDesignWaterFlowRate, !- Performance Input Method",
" , !- Outdoor Air Inlet Node Name",
" , !- Heat Rejection Capacity and Nominal Capacity Sizing Ratio",
" , !- Standard Design Capacity {W}",
" Autosize, !- Design Air Flow Rate U-factor Times Area Value {W/K}",
" Autosize, !- Design Water Flow Rate {m3/s}",
" , !- User Specified Design Capacity {W}",
" 46.11, !- Design Entering Water Temperature {C}",
" 35, !- Design Entering Air Temperature {C}",
" 25.6; !- Design Entering Air Wet-bulb Temperature {C}",
});

ASSERT_TRUE(process_idf(idf_objects));

EvapFluidCoolerSpecs *ptr =
EvapFluidCoolerSpecs::factory(*state, DataPlant::PlantEquipmentType::EvapFluidCooler_SingleSpd, "BIG EVAPORATIVEFLUIDCOOLER");

state->dataPlnt->PlantLoop.allocate(1);
state->dataPlnt->PlantLoop(1).PlantSizNum = 0;
ptr->plantLoc.loopNum = 1;

// Necessary to trigger the crash from #
state->dataPlnt->PlantFirstSizesOkayToFinalize = false;

EXPECT_TRUE(ptr->DesignWaterFlowRateWasAutoSized);
EXPECT_TRUE(ptr->HighSpeedAirFlowRateWasAutoSized);
EXPECT_TRUE(ptr->HighSpeedFanPowerWasAutoSized);
EXPECT_TRUE(ptr->HighSpeedEvapFluidCoolerUAWasAutoSized);

ptr->SizeEvapFluidCooler(*state);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Realized the same was happening for EvaporativeFluidCooler:XX objects, so added a test there too

Comment on lines 1354 to +1358
if (PltSizCondNum > 0) {

// Check when the user specified Condenser/Evaporative Fluid Cooler water design setpoint
// temperature is less than design inlet air wet bulb temperature
Real64 DesignEnteringAirWetBulb = 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.

Fix is to basically ensure the check is done INSIDE the if(PltSizCondNum > 0)

If PltSizCondNum is not > 0, it'll throw anyways

@@ -1380,28 +1403,6 @@ namespace EvaporativeFluidCoolers {
ShowFatalError(state, "Autosizing of evaporative fluid cooler condenser flow rate requires a loop Sizing:Plant object.");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Throw when PltSizCondNum is not > 0 is here.

Comment on lines 957 to 975
// This is to trap when the user specified Condenser/Fluid Cooler water design setpoint temperature is less than design inlet air dry bulb
// temperature
auto ensureSizingPlantExitTempIsNotLessThanDesignEnteringAirTemp = [this, &state, PltSizCondNum]() {
if (state.dataSize->PlantSizData(PltSizCondNum).ExitTemp <= this->DesignEnteringAirTemp && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
ShowSevereError(state, format("Error when autosizing the UA value for fluid cooler = {}.", this->Name));
ShowContinueError(state,
format("Design Loop Exit Temperature ({:.2R} C) must be greater than design entering air dry-bulb temperature "
"({:.2R} C) when autosizing the fluid cooler UA.",
state.dataSize->PlantSizData(PltSizCondNum).ExitTemp,
this->DesignEnteringAirTemp));
ShowContinueError(state,
"It is recommended that the Design Loop Exit Temperature = design inlet air dry-bulb temp plus the Fluid Cooler "
"design approach temperature (e.g., 4 C).");
ShowContinueError(state,
"If using HVACTemplate:Plant:ChilledWaterLoop, then check that input field Condenser Water Design Setpoint must be "
"> design inlet air dry-bulb temp if autosizing the Fluid Cooler.");
ShowFatalError(state, "Review and revise design input values as appropriate.");
}
};
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fluid cooler had the same block 4 times, so I reuse a lambda instead

// This is to trap when the user specified Condenser/Fluid Cooler water design setpoint temperature is less than design inlet air dry bulb
// temperature
auto ensureSizingPlantExitTempIsNotLessThanDesignEnteringAirTemp = [this, &state, PltSizCondNum]() {
if (state.dataSize->PlantSizData(PltSizCondNum).ExitTemp <= this->DesignEnteringAirTemp && state.dataPlnt->PlantFirstSizesOkayToFinalize) {
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 don't think it's necessary to delay until PlantFirstSizesOkayToFinalize is true, but I didn't want to change the existing behavior

@jmarrec jmarrec force-pushed the 10817_CrashFluidCooler branch from 7284c44 to 4aaa7c0 Compare December 13, 2024 12:42
Copy link

⚠️ Regressions detected on macos-14 for commit f5ebb77

Regression Summary
  • Table Big Diffs: 6

@jmarrec
Copy link
Contributor Author

jmarrec commented Dec 16, 2024

Regressions are all expected. The ASHRAE901_OfficeLarge_STD2019_Denver variations have an autosized Design Water Flow Rate, so the Design Leaving Water Temperature was already being correctly calculated, so no diff here (and approach/range), only the m3/s sig digits:

Before:

image

After:

image


FluidCooler.idf

Design Water Flow Rate is harcoded to 0.001388, so the Design Leaving Water Temperature was zero before and approach & range were wrong

before:

image

After:

image


FluidCoolerTwoSpeed

Same here as the ASHRAE901, the Design Water Flow Rate is autosized so the Design Leaving Water Temperature was correctly calcualted

before:

image

After:

image

@nrel-bot-2
Copy link

@jmarrec it has been 7 days since this pull request was last updated.

@nrel-bot-2
Copy link

@jmarrec it has been 10 days since this pull request was last updated.

@nrel-bot-2
Copy link

@jmarrec it has been 8 days since this pull request was last updated.

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 NotIDDChange Code does not impact IDD (can be merged after IO freeze)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Crash in Fluid Cooler Code
2 participants