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 #5313 - AirLoopHVACUnitaryHeatPump(Multispeed) fixes #5322

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

Conversation

jmarrec
Copy link
Collaborator

@jmarrec jmarrec commented Dec 18, 2024

Pull request overview

Pull Request Author

  • Model API Changes / Additions
  • Any new or modified fields have been implemented in the EnergyPlus ForwardTranslator (and ReverseTranslator as appropriate)
  • Model API methods are tested (in src/model/test)
  • EnergyPlus ForwardTranslator Tests (in src/energyplus/Test)
  • If a new object or method, added a test in NREL/OpenStudio-resources: Add Link
  • If needed, added VersionTranslation rules for the objects (src/osversion/VersionTranslator.cpp)
  • Verified that C# bindings built fine on Windows, partial classes used as needed, etc.
  • All new and existing tests passes
  • If methods have been deprecated, update rest of code to use the new methods

Labels:

  • If change to an IDD file, add the label IDDChange
  • If breaking existing API, add the label APIChange
  • If deemed ready, add label Pull Request - Ready for CI so that CI builds your PR

Review Checklist

This will not be exhaustively relevant to every PR.

  • Perform a Code Review on GitHub
  • Code Style, strip trailing whitespace, etc.
  • All related changes have been implemented: model changes, model tests, FT changes, FT tests, VersionTranslation, OS App
  • Labeling is ok
  • 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

…eatPumpAirToAirMultiSpeed

```
[==========] Running 12 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 12 tests from ModelFixture
[ RUN      ] ModelFixture.AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_GettersSetters
[       OK ] ModelFixture.AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_GettersSetters (51 ms)
[ RUN      ] ModelFixture.AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_addToNode
/media/DataExt4/Software/Others/OpenStudio2/src/model/test/AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_GTest.cpp:310: Failure
Value of: testObject.addToNode(inletNode)
  Actual: true
Expected: false

/media/DataExt4/Software/Others/OpenStudio2/src/model/test/AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_GTest.cpp:311: Failure
Expected equality of these values:
  5
  airLoop.demandComponents().size()
    Which is: 7

/media/DataExt4/Software/Others/OpenStudio2/src/model/test/AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_GTest.cpp:316: Failure
Value of: testObject.addToNode(supplyOutletNode)
  Actual: true
Expected: false

/media/DataExt4/Software/Others/OpenStudio2/src/model/test/AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_GTest.cpp:317: Failure
Expected equality of these values:
  5
  plantLoop.supplyComponents().size()
    Which is: 7

/media/DataExt4/Software/Others/OpenStudio2/src/model/test/AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_GTest.cpp:321: Failure
Value of: testObject.addToNode(demandOutletNode)
  Actual: true
Expected: false

/media/DataExt4/Software/Others/OpenStudio2/src/model/test/AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_GTest.cpp:322: Failure
Expected equality of these values:
  5
  plantLoop.demandComponents().size()
    Which is: 7

/media/DataExt4/Software/Others/OpenStudio2/src/model/test/AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_GTest.cpp:331: Failure
Expected equality of these values:
  5
  airLoop.supplyComponents().size()
    Which is: 3

[  FAILED  ] ModelFixture.AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_addToNode (106 ms)
[ RUN      ] ModelFixture.AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_Ctor_WrongChildType
/media/DataExt4/Software/Others/OpenStudio2/src/model/test/AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_GTest.cpp:346: Failure
Expected equality of these values:
  0
  m.getConcreteModelObjects<AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed>().size()
    Which is: 1

[  FAILED  ] ModelFixture.AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_Ctor_WrongChildType (18 ms)
[ RUN      ] ModelFixture.AirLoopHVACUnitaryHeatPumpAirToAir_AirLoopHVACUnitaryHeatPumpAirToAir
Running main() from gmock_main.cc
[       OK ] ModelFixture.AirLoopHVACUnitaryHeatPumpAirToAir_AirLoopHVACUnitaryHeatPumpAirToAir (90 ms)
[ RUN      ] ModelFixture.AirLoopHVACUnitaryHeatPumpAirToAir_addToNode
[       OK ] ModelFixture.AirLoopHVACUnitaryHeatPumpAirToAir_addToNode (75 ms)
[ RUN      ] ModelFixture.AirLoopHVACUnitaryHeatPumpAirToAir_VariableSpeedCoils
[       OK ] ModelFixture.AirLoopHVACUnitaryHeatPumpAirToAir_VariableSpeedCoils (65 ms)
[ RUN      ] ModelFixture.AirLoopHVACUnitaryHeatPumpAirToAir_CoilSystemIntegratedHeatPumpAirSource
[       OK ] ModelFixture.AirLoopHVACUnitaryHeatPumpAirToAir_CoilSystemIntegratedHeatPumpAirSource (145 ms)
[ RUN      ] ModelFixture.AirLoopHVACUnitaryHeatPumpAirToAir_Ctor_WrongChildType
[BOOST_ASSERT] <2> Assertion result failed on line 244 of openstudio::model::HVACComponent openstudio::model::detail::AirLoopHVACUnitaryHeatPumpAirToAir_Impl::supplementalHeatingCoil() const in file /media/DataExt4/Software/Others/OpenStudio2/src/model/AirLoopHVACUnitaryHeatPumpAirToAir.cpp.
openstudio_model_tests: /media/DataExt4/Software/Others/OpenStudio2/src/model/test/../../utilities/core/Assert.hpp:37: void boost::assertion_failed(const char*, const char*, const char*, long int): Assertion `false' failed.
Aborted (core dumped)
```
…ove is called, so children should check optional subcomponent
@jmarrec jmarrec added severity - Normal Bug component - HVAC component - Model Pull Request - Ready for CI This pull request if finalized and is ready for continuous integration verification prior to merge. labels Dec 18, 2024
@jmarrec jmarrec self-assigned this Dec 18, 2024
@jmarrec jmarrec force-pushed the 5313_UnitaryHPAirToAir_SupplHC branch from 228d9cb to 1ede1bd Compare December 18, 2024 15:50
Comment on lines +216 to +229
TEST_F(ModelFixture, AirLoopHVACUnitaryHeatPumpAirToAir_Ctor_WrongChildType) {
Model m;
Schedule s = m.alwaysOnDiscreteSchedule();
FanConstantVolume supplyFan(m, s);

CoilCoolingDXVariableSpeed cc(m);
CoilHeatingDXVariableSpeed hc(m);

// Wrong supplemental heating coil type, I expect a graceful failure, not a segfault
CoilHeatingDXVariableSpeed suppHC(m);

// The segfault is caught here, but if graceful, the remove() was called!
EXPECT_THROW(AirLoopHVACUnitaryHeatPumpAirToAir(m, s, supplyFan, hc, cc, suppHC), openstudio::Exception);
EXPECT_EQ(0, m.getConcreteModelObjects<AirLoopHVACUnitaryHeatPumpAirToAir>().size());
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Before fix:

[BOOST_ASSERT] <2> Assertion result failed on line 244 of openstudio::model::HVACComponent openstudio::model::detail::AirLoopHVACUnitaryHeatPumpAirToAir_Impl::supplementalHeatingCoil() const in file /media/DataExt4/Software/Others/OpenStudio2/src/model/AirLoopHVACUnitaryHeatPumpAirToAir.cpp.
openstudio_model_tests: /media/DataExt4/Software/Others/OpenStudio2/src/model/test/../../utilities/core/Assert.hpp:37: void boost::assertion_failed(const char*, const char*, const char*, long int): Assertion `false' failed.
Aborted (core dumped)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We had this test file, yet it was fully empty... We should do another pass to find untested classes @kbenne @DavidGoldwasser

Comment on lines +334 to +347
TEST_F(ModelFixture, AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_Ctor_WrongChildType) {
Model m;
Schedule s = m.alwaysOnDiscreteSchedule();
FanConstantVolume supplyFan(m, s);

// Wrong cooling type, I expect a graceful failure, not a segfault
CoilCoolingDXSingleSpeed cc(m);
CoilHeatingElectricMultiStage hc(m);
CoilHeatingElectric suppHC(m);

// The segfault is caught here, but if graceful, the remove() was called!
EXPECT_THROW(AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed(m, supplyFan, hc, cc, suppHC), openstudio::Exception);
EXPECT_EQ(0, m.getConcreteModelObjects<AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed>().size());
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Before fix, this doesn't segfault because there is a LOG_AND_THROW and not an OS_ASSERT, but the remove() is never called though.

[ RUN      ] ModelFixture.AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_Ctor_WrongChildType
/media/DataExt4/Software/Others/OpenStudio2/src/model/test/AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_GTest.cpp:346: Failure
Expected equality of these values:
  0
  m.getConcreteModelObjects<AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed>().size()
    Which is: 1

Comment on lines +289 to +332
TEST_F(ModelFixture, AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_addToNode) {
Model m;
Schedule s = m.alwaysOnDiscreteSchedule();
FanConstantVolume supplyFan(m, s);

CoilCoolingDXMultiSpeed cc(m);
CoilHeatingElectricMultiStage hc(m);

CoilHeatingElectric suppHC(m);

AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed testObject(m, supplyFan, hc, cc, suppHC);

AirLoopHVAC airLoop(m);

Node supplyOutletNode = airLoop.supplyOutletNode();
EXPECT_EQ(2, airLoop.supplyComponents().size());
EXPECT_TRUE(testObject.addToNode(supplyOutletNode));
EXPECT_EQ(3, airLoop.supplyComponents().size());

EXPECT_EQ(5, airLoop.demandComponents().size());
Node inletNode = airLoop.zoneSplitter().lastOutletModelObject()->cast<Node>();
EXPECT_FALSE(testObject.addToNode(inletNode));
EXPECT_EQ(5, airLoop.demandComponents().size());

PlantLoop plantLoop(m);
supplyOutletNode = plantLoop.supplyOutletNode();
EXPECT_EQ(5, plantLoop.supplyComponents().size());
EXPECT_FALSE(testObject.addToNode(supplyOutletNode));
EXPECT_EQ(5, plantLoop.supplyComponents().size());

Node demandOutletNode = plantLoop.demandOutletNode();
EXPECT_EQ(5, plantLoop.demandComponents().size());
EXPECT_FALSE(testObject.addToNode(demandOutletNode));
EXPECT_EQ(5, plantLoop.demandComponents().size());

auto testObjectClone = testObject.clone(m).cast<AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed>();
// Clone should reset the inlet/outlet nodes
ASSERT_FALSE(testObjectClone.inletModelObject());
ASSERT_FALSE(testObjectClone.outletModelObject());

supplyOutletNode = airLoop.supplyOutletNode();
EXPECT_TRUE(testObjectClone.addToNode(supplyOutletNode));
EXPECT_EQ(5, airLoop.supplyComponents().size());
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Completely wrong originally.

The Clone method was using MdoelObject_Impl::clone, which does not reset the inlet/outlet nodes.
And the addToNode was not overriden so it'd accept ANY connection.

[ RUN      ] ModelFixture.AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_addToNode
/media/DataExt4/Software/Others/OpenStudio2/src/model/test/AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_GTest.cpp:310: Failure
Value of: testObject.addToNode(inletNode)
  Actual: true
Expected: false

/media/DataExt4/Software/Others/OpenStudio2/src/model/test/AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_GTest.cpp:311: Failure
Expected equality of these values:
  5
  airLoop.demandComponents().size()
    Which is: 7

/media/DataExt4/Software/Others/OpenStudio2/src/model/test/AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_GTest.cpp:316: Failure
Value of: testObject.addToNode(supplyOutletNode)
  Actual: true
Expected: false

/media/DataExt4/Software/Others/OpenStudio2/src/model/test/AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_GTest.cpp:317: Failure
Expected equality of these values:
  5
  plantLoop.supplyComponents().size()
    Which is: 7

/media/DataExt4/Software/Others/OpenStudio2/src/model/test/AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_GTest.cpp:321: Failure
Value of: testObject.addToNode(demandOutletNode)
  Actual: true
Expected: false

/media/DataExt4/Software/Others/OpenStudio2/src/model/test/AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_GTest.cpp:322: Failure
Expected equality of these values:
  5
  plantLoop.demandComponents().size()
    Which is: 7

/media/DataExt4/Software/Others/OpenStudio2/src/model/test/AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_GTest.cpp:331: Failure
Expected equality of these values:
  5
  airLoop.supplyComponents().size()
    Which is: 3

@@ -11569,6 +11569,7 @@ OS:AirLoopHVAC:UnitaryHeatPump:AirToAir,
\type object-list
\required-field
\object-list HeatingCoilsGasElec
\object-list HeatingCoilsWater
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Specific for #5313 - Suppl HC should allow Coil:Heating:Water (Coil:Heating:Steam isn't wrapped in OS)

Comment on lines +189 to +192
boost::optional<HVACComponent> optionalSupplyAirFan() const;
boost::optional<HVACComponent> optionalHeatingCoil() const;
boost::optional<HVACComponent> optionalCoolingCoil() const;
boost::optional<HVACComponent> optionalSupplementalHeatingCoil() const;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Remove useless methods AsModelObject (never used anywhere), and replace with actual useful methods.

Comment on lines +119 to +131
// Avoid crashing when calling remove() in Ctor when failing to set one of the child component by calling the optional one
if (boost::optional<HVACComponent> supplyFan = this->optionalSupplyAirFan()) {
result.push_back(std::move(*supplyFan));
}
if (boost::optional<HVACComponent> coolingCoil = this->optionalCoolingCoil()) {
result.push_back(std::move(*coolingCoil));
}
if (boost::optional<HVACComponent> heatingCoil = this->optionalHeatingCoil()) {
result.push_back(std::move(*heatingCoil));
}
if (boost::optional<HVACComponent> supplementalHeatingCoil = this->optionalSupplementalHeatingCoil()) {
result.push_back(std::move(*supplementalHeatingCoil));
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fix for the crash is here

Comment on lines +440 to +441
} else if (hvacComponent.optionalCast<CoilHeatingWater>()) {
isTypeOK = true;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

And here too

Comment on lines +600 to +608
bool AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_Impl::addToNode(Node& node) {
if (boost::optional<AirLoopHVAC> airLoop = node.airLoopHVAC()) {
if (airLoop->supplyComponent(node.handle())) {
return StraightComponent_Impl::addToNode(node);
}
}

return false;
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Restrict addToNode.

Note that ideally we should also allow demand side of a plant loop and connect the Heat Recovery Water Nodes there, but outside the scope and no one ever asked for it.

ModelObject AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed_Impl::clone(Model model) const {
auto modelObjectClone = ModelObject_Impl::clone(model).cast<AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed>();
auto modelObjectClone = StraightComponent_Impl::clone(model).cast<AirLoopHVACUnitaryHeatPumpAirToAirMultiSpeed>();
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixup clone here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component - HVAC component - Model Pull Request - Ready for CI This pull request if finalized and is ready for continuous integration verification prior to merge. severity - Normal Bug
Projects
None yet
2 participants