-
Notifications
You must be signed in to change notification settings - Fork 233
#5350 - Changes to Support CoilSystem:Cooling:Water #5404
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
Changes from 10 commits
041adbd
310a14f
d0cc34b
ba57cda
4f3e2d4
63acda6
b264a56
53780c8
14c7357
95c4727
3d6d145
868633a
64dd179
51a0ae3
61ea54d
e1705d9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -273,48 +273,68 @@ namespace model { | |
| } | ||
|
|
||
| bool CoilCoolingWater_Impl::addToNode(Node& node) { | ||
| bool success(false); | ||
| bool success = false; | ||
|
|
||
| auto t_containingHVACComponent = containingHVACComponent(); | ||
| auto t_airLoop = node.airLoopHVAC(); | ||
|
|
||
| if (t_airLoop && t_containingHVACComponent && t_containingHVACComponent->optionalCast<CoilSystemCoolingWaterHeatExchangerAssisted>()) { | ||
| LOG(Warn, this->briefDescription() | ||
| << " cannot be connected directly to an AirLoopHVAC when it's part of a parent CoilSystemCoolingWaterHeatExchangerAssisted. " | ||
| "Please call CoilSystemCoolingWaterHeatExchangerAssisted::addToNode instead"); | ||
|
|
||
| /* } else if (t_airLoop && t_containingHVACComponent && t_containingHVACComponent->optionalCast<CoilSystemCoolingWater>()) { | ||
| LOG(Warn, this->briefDescription() | ||
| << " cannot be connected directly to an AirLoopHVAC when it's part of a parent CoilSystemCoolingWater. " | ||
| "Please call CoilSystemCoolingWater::addToNode instead"); */ | ||
| // Reject adding coils parent of a Parent System | ||
| if (t_airLoop && t_containingHVACComponent) { | ||
| if (t_containingHVACComponent->optionalCast<CoilSystemCoolingWaterHeatExchangerAssisted>()) { | ||
| LOG(Warn, this->briefDescription() | ||
| << " cannot be connected directly to an AirLoopHVAC when it's part of a parent CoilSystemCoolingWaterHeatExchangerAssisted. " | ||
| "Please call CoilSystemCoolingWaterHeatExchangerAssisted::addToNode instead"); | ||
| return false; | ||
| } | ||
|
|
||
| } else { | ||
| if (t_containingHVACComponent->optionalCast<CoilSystemCoolingWater>() | ||
| && t_containingHVACComponent->cast<CoilSystemCoolingWater>().coolingCoil().handle() == this->handle()) { | ||
| LOG(Warn, this->briefDescription() | ||
| << " cannot be connected directly to an AirLoopHVAC when it's the primary cooling coil of a parent CoilSystemCoolingWater. " | ||
| "Please call CoilSystemCoolingWater::addToNode instead"); | ||
| return false; | ||
| } | ||
| } | ||
|
Comment on lines
+281
to
+297
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The primary cooling coil of the CoilSystemCoolingWater shouldn't be connected directly to an AirLoopHVAC, at least that's my interpretation of the E+ testfiles. |
||
|
|
||
| success = WaterToAirComponent_Impl::addToNode(node); | ||
| auto t_containingZoneHVACComponent = containingZoneHVACComponent(); | ||
| success = WaterToAirComponent_Impl::addToNode(node); | ||
| if (!success) { | ||
| return false; | ||
| } | ||
| // We only add the controller if we are not part of a containing ZoneHVACComponent, and we have a PlantLoop assigned | ||
| if (containingZoneHVACComponent() || !waterInletModelObject()) { | ||
| // We're done | ||
| return true; | ||
| } | ||
|
Comment on lines
+299
to
+307
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. exit early when we definitely don't need a controller water coil |
||
|
|
||
| if (success && (!t_containingZoneHVACComponent)) { | ||
| if (auto t_waterInletModelObject = waterInletModelObject()) { | ||
| if (auto oldController = controllerWaterCoil()) { | ||
| if (!openstudio::istringEqual(oldController->action().get(), "Reverse")) { | ||
| LOG(Warn, | ||
| briefDescription() | ||
| << " has an existing ControllerWaterCoil with action set to something else than 'Reverse'. Make sure this is what you want"); | ||
| } | ||
| } else { | ||
| if (t_containingHVACComponent && t_containingHVACComponent->optionalCast<CoilSystemCoolingWater>()) { | ||
| // no-op | ||
| } else { | ||
| Model t_model = model(); | ||
| ControllerWaterCoil controller(t_model); | ||
| controller.getImpl<ControllerWaterCoil_Impl>()->setWaterCoil(getObject<HVACComponent>()); | ||
| controller.setAction("Reverse"); | ||
| } | ||
| // We don't need a controller if we are part of a CoilSystemCoolingWater (directly, or indirectly via a | ||
| // CoilSystemCoolingWaterHeatExchangerAssisted) | ||
| bool needAController = true; | ||
| if (t_containingHVACComponent) { | ||
| if (t_containingHVACComponent->optionalCast<CoilSystemCoolingWater>()) { | ||
| needAController = false; | ||
| } else if (auto hxAssisted_ = t_containingHVACComponent->optionalCast<CoilSystemCoolingWaterHeatExchangerAssisted>()) { | ||
| if (auto parent_ = hxAssisted_->containingHVACComponent()) { | ||
| if (parent_->optionalCast<CoilSystemCoolingWater>()) { | ||
| needAController = false; | ||
|
Comment on lines
+309
to
+318
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need a ControllerWaterCoil except if we're directly or indirectly (via a CoilSystemCoolingWaterHeatExchangerAssisted) part of a CoilSystemCoolingWater. |
||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (auto oldController_ = controllerWaterCoil()) { | ||
| if (!needAController) { | ||
| oldController_->remove(); | ||
| } else if (!openstudio::istringEqual(oldController_->action().get(), "Reverse")) { | ||
| LOG(Warn, briefDescription() | ||
| << " has an existing ControllerWaterCoil with action set to something else than 'Reverse'. Make sure this is what you want"); | ||
| } | ||
| } else if (needAController) { | ||
| Model t_model = model(); | ||
| ControllerWaterCoil controller(t_model); | ||
| controller.getImpl<ControllerWaterCoil_Impl>()->setWaterCoil(getObject<HVACComponent>()); | ||
| controller.setAction("Reverse"); | ||
| } | ||
|
Comment on lines
+324
to
+336
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we need a controller:
If we don't need a controller, just remove any existing one |
||
|
|
||
| return success; | ||
| } | ||
|
|
||
|
|
@@ -389,7 +409,7 @@ namespace model { | |
| if (coilSystem.coolingCoil().handle() == handle()) { | ||
| return coilSystem; | ||
| } | ||
| if (boost::optional<WaterToAirComponent> companionCoilUsedForHeatRecovery = coilSystem.companionCoilUsedForHeatRecovery()) { | ||
| if (boost::optional<HVACComponent> companionCoilUsedForHeatRecovery = coilSystem.companionCoilUsedForHeatRecovery()) { | ||
| if (companionCoilUsedForHeatRecovery->handle() == this->handle()) { | ||
| return coilSystem; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,10 +8,12 @@ | |
|
|
||
| #include "Schedule.hpp" | ||
| #include "Schedule_Impl.hpp" | ||
| #include "WaterToAirComponent.hpp" | ||
| #include "WaterToAirComponent_Impl.hpp" | ||
| #include "HVACComponent.hpp" | ||
| #include "HVACComponent_Impl.hpp" | ||
| #include "CoilCoolingWater.hpp" | ||
| #include "CoilCoolingWater_Impl.hpp" | ||
| #include "CoilSystemCoolingWaterHeatExchangerAssisted.hpp" | ||
| #include "CoilSystemCoolingWaterHeatExchangerAssisted_Impl.hpp" | ||
| #include "Model.hpp" | ||
| #include "Model_Impl.hpp" | ||
| #include "Node.hpp" | ||
|
|
@@ -87,24 +89,47 @@ namespace model { | |
|
|
||
| std::vector<ModelObject> CoilSystemCoolingWater_Impl::children() const { | ||
| std::vector<ModelObject> result; | ||
| if (OptionalWaterToAirComponent intermediate = optionalCoolingCoil()) { | ||
| if (OptionalHVACComponent intermediate = optionalCoolingCoil()) { | ||
| result.push_back(*intermediate); | ||
| } | ||
| if (OptionalWaterToAirComponent intermediate = optionalCompanionCoilUsedForHeatRecovery()) { | ||
| if (OptionalHVACComponent intermediate = companionCoilUsedForHeatRecovery()) { | ||
| result.push_back(*intermediate); | ||
| } | ||
|
|
||
| return result; | ||
| } | ||
|
|
||
| std::vector<IdfObject> CoilSystemCoolingWater_Impl::remove() { | ||
| std::vector<IdfObject> result; | ||
|
|
||
| if (auto c_ = optionalCoolingCoil()) { // This is false when the explicit ctor throws | ||
| if (boost::optional<WaterToAirComponent> cc_ = c_->optionalCast<WaterToAirComponent>()) { | ||
| cc_->removeFromPlantLoop(); | ||
| } else if (auto cc_ = c_->optionalCast<CoilSystemCoolingWaterHeatExchangerAssisted>()) { | ||
| cc_->coolingCoil().removeFromPlantLoop(); | ||
| } else { | ||
| OS_ASSERT(false); | ||
| } | ||
| } | ||
| if (auto companionCoil_ = companionCoilUsedForHeatRecovery()) { | ||
| if (auto cc_ = companionCoil_->optionalCast<WaterToAirComponent>()) { | ||
| cc_->removeFromPlantLoop(); | ||
| } else { | ||
| OS_ASSERT(false); | ||
| } | ||
| } | ||
|
|
||
| return StraightComponent_Impl::remove(); | ||
| } | ||
|
|
||
| ModelObject CoilSystemCoolingWater_Impl::clone(Model model) const { | ||
| auto coilSystemClone = StraightComponent_Impl::clone(model).cast<CoilSystemCoolingWater>(); | ||
|
|
||
| if (OptionalWaterToAirComponent intermediate = optionalCoolingCoil()) { | ||
| coilSystemClone.setCoolingCoil(intermediate->clone(model).cast<WaterToAirComponent>()); | ||
| if (OptionalHVACComponent intermediate = optionalCoolingCoil()) { | ||
| coilSystemClone.setCoolingCoil(intermediate->clone(model).cast<HVACComponent>()); | ||
| } | ||
| if (OptionalWaterToAirComponent intermediate = optionalCompanionCoilUsedForHeatRecovery()) { | ||
| coilSystemClone.setCompanionCoilUsedForHeatRecovery(intermediate->clone(model).cast<WaterToAirComponent>()); | ||
| if (OptionalHVACComponent intermediate = companionCoilUsedForHeatRecovery()) { | ||
| coilSystemClone.setCompanionCoilUsedForHeatRecovery(intermediate->clone(model).cast<HVACComponent>()); | ||
| } | ||
|
|
||
| return std::move(coilSystemClone); | ||
|
|
@@ -127,50 +152,10 @@ namespace model { | |
| } | ||
|
|
||
| boost::optional<HVACComponent> CoilSystemCoolingWater_Impl::containingHVACComponent() const { | ||
| // AirLoopHVACUnitarySystem | ||
| std::vector<AirLoopHVACUnitarySystem> airLoopHVACUnitarySystems = this->model().getConcreteModelObjects<AirLoopHVACUnitarySystem>(); | ||
|
|
||
| for (const auto& airLoopHVACUnitarySystem : airLoopHVACUnitarySystems) { | ||
| if (boost::optional<HVACComponent> coolingCoil = airLoopHVACUnitarySystem.coolingCoil()) { | ||
| if (coolingCoil->handle() == this->handle()) { | ||
| return airLoopHVACUnitarySystem; | ||
| } | ||
| } | ||
| } | ||
|
Comment on lines
154
to
-139
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CANNOT be part of a containing HVACComponent AFAIK |
||
|
|
||
| return boost::none; | ||
| } | ||
|
|
||
| boost::optional<ZoneHVACComponent> CoilSystemCoolingWater_Impl::containingZoneHVACComponent() const { | ||
|
|
||
| // ZoneHVACFourPipeFanCoil | ||
| std::vector<ZoneHVACFourPipeFanCoil> zoneHVACFourPipeFanCoils; | ||
|
|
||
| zoneHVACFourPipeFanCoils = this->model().getConcreteModelObjects<ZoneHVACFourPipeFanCoil>(); | ||
|
Comment on lines
158
to
-149
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CANNOT be part of a containing ZoneHVACComponent AFAIK This is from the E+ IDD, there are ZERO possible references. |
||
|
|
||
| for (const auto& zoneHVACFourPipeFanCoil : zoneHVACFourPipeFanCoils) { | ||
| if (boost::optional<HVACComponent> coil = zoneHVACFourPipeFanCoil.coolingCoil()) { | ||
| if (coil->handle() == this->handle()) { | ||
| return zoneHVACFourPipeFanCoil; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // ZoneHVACUnitVentilator | ||
| std::vector<ZoneHVACUnitVentilator> zoneHVACUnitVentilators; | ||
|
|
||
| zoneHVACUnitVentilators = this->model().getConcreteModelObjects<ZoneHVACUnitVentilator>(); | ||
|
|
||
| for (const auto& zoneHVACUnitVentilator : zoneHVACUnitVentilators) { | ||
| if (boost::optional<HVACComponent> coil = zoneHVACUnitVentilator.coolingCoil()) { | ||
| if (coil->handle() == this->handle()) { | ||
| return zoneHVACUnitVentilator; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // ZoneHVAC:WindowAirConditioner not wrapped | ||
|
|
||
| return boost::none; | ||
| } | ||
|
|
||
|
|
@@ -198,8 +183,8 @@ namespace model { | |
| return value.get(); | ||
| } | ||
|
|
||
| WaterToAirComponent CoilSystemCoolingWater_Impl::coolingCoil() const { | ||
| boost::optional<WaterToAirComponent> value = optionalCoolingCoil(); | ||
| HVACComponent CoilSystemCoolingWater_Impl::coolingCoil() const { | ||
| boost::optional<HVACComponent> value = optionalCoolingCoil(); | ||
| if (!value) { | ||
| LOG_AND_THROW(briefDescription() << " does not have an Cooling Coil attached."); | ||
| } | ||
|
|
@@ -236,8 +221,8 @@ namespace model { | |
| return value.get(); | ||
| } | ||
|
|
||
| boost::optional<WaterToAirComponent> CoilSystemCoolingWater_Impl::companionCoilUsedForHeatRecovery() const { | ||
| return optionalCompanionCoilUsedForHeatRecovery(); | ||
| boost::optional<HVACComponent> CoilSystemCoolingWater_Impl::companionCoilUsedForHeatRecovery() const { | ||
| return getObject<ModelObject>().getModelObjectTarget<HVACComponent>(OS_CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery); | ||
| } | ||
|
|
||
| bool CoilSystemCoolingWater_Impl::setAvailabilitySchedule(Schedule& schedule) { | ||
|
|
@@ -246,7 +231,7 @@ namespace model { | |
| return result; | ||
| } | ||
|
|
||
| bool CoilSystemCoolingWater_Impl::setCoolingCoil(const WaterToAirComponent& coolingCoil) { | ||
| bool CoilSystemCoolingWater_Impl::setCoolingCoil(const HVACComponent& coolingCoil) { | ||
| const bool result = setPointer(OS_CoilSystem_Cooling_WaterFields::CoolingCoil, coolingCoil.handle()); | ||
| return result; | ||
| } | ||
|
|
@@ -286,9 +271,16 @@ namespace model { | |
| return result; | ||
| } | ||
|
|
||
| bool CoilSystemCoolingWater_Impl::setCompanionCoilUsedForHeatRecovery(const WaterToAirComponent& companionCoilUsedForHeatRecovery) { | ||
| const bool result = setPointer(OS_CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery, companionCoilUsedForHeatRecovery.handle()); | ||
| return result; | ||
| bool CoilSystemCoolingWater_Impl::setCompanionCoilUsedForHeatRecovery(const HVACComponent& companionCoilUsedForHeatRecovery) { | ||
| if (companionCoilUsedForHeatRecovery.iddObjectType() == IddObjectType::OS_Coil_Cooling_Water) { | ||
| const bool result = | ||
| setPointer(OS_CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery, companionCoilUsedForHeatRecovery.handle()); | ||
| return result; | ||
| } else { | ||
| LOG(Warn, "Invalid Companion Coil Used For Heat Recovery Type (expected CoilCoolingWater, not '" | ||
| << companionCoilUsedForHeatRecovery.iddObjectType().valueName() << "') for " << briefDescription()); | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| void CoilSystemCoolingWater_Impl::resetCompanionCoilUsedForHeatRecovery() { | ||
|
|
@@ -300,12 +292,8 @@ namespace model { | |
| return getObject<ModelObject>().getModelObjectTarget<Schedule>(OS_CoilSystem_Cooling_WaterFields::AvailabilityScheduleName); | ||
| } | ||
|
|
||
| boost::optional<WaterToAirComponent> CoilSystemCoolingWater_Impl::optionalCoolingCoil() const { | ||
| return getObject<ModelObject>().getModelObjectTarget<WaterToAirComponent>(OS_CoilSystem_Cooling_WaterFields::CoolingCoil); | ||
| } | ||
|
|
||
| boost::optional<WaterToAirComponent> CoilSystemCoolingWater_Impl::optionalCompanionCoilUsedForHeatRecovery() const { | ||
| return getObject<ModelObject>().getModelObjectTarget<WaterToAirComponent>(OS_CoilSystem_Cooling_WaterFields::CompanionCoilUsedForHeatRecovery); | ||
| boost::optional<HVACComponent> CoilSystemCoolingWater_Impl::optionalCoolingCoil() const { | ||
| return getObject<ModelObject>().getModelObjectTarget<HVACComponent>(OS_CoilSystem_Cooling_WaterFields::CoolingCoil); | ||
| } | ||
|
|
||
| } // namespace detail | ||
|
|
@@ -335,17 +323,20 @@ namespace model { | |
| OS_ASSERT(ok); | ||
| } | ||
|
|
||
| CoilSystemCoolingWater::CoilSystemCoolingWater(const Model& model, const WaterToAirComponent& coolingCoil) | ||
| CoilSystemCoolingWater::CoilSystemCoolingWater(const Model& model, const HVACComponent& coolingCoil) | ||
| : StraightComponent(CoilSystemCoolingWater::iddObjectType(), model) { | ||
| OS_ASSERT(getImpl<detail::CoilSystemCoolingWater_Impl>()); | ||
|
|
||
| bool ok = true; | ||
| ok = setCoolingCoil(coolingCoil); | ||
| if (!ok) { | ||
| remove(); | ||
| LOG_AND_THROW("Unable to set " << briefDescription() << "'s Cooling Coil " << coolingCoil.briefDescription() << "."); | ||
| } | ||
|
Comment on lines
342
to
+341
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is how you handle the explicit ctor being passed the wrong object, which can definitely happen. |
||
| auto alwaysOn = model.alwaysOnDiscreteSchedule(); | ||
| ok = setAvailabilitySchedule(alwaysOn); | ||
| OS_ASSERT(ok); | ||
|
|
||
| ok = setCoolingCoil(coolingCoil); | ||
| OS_ASSERT(ok); | ||
| ok = setDehumidificationControlType("None"); | ||
| OS_ASSERT(ok); | ||
| ok = setRunonSensibleLoad(true); | ||
|
|
@@ -372,7 +363,7 @@ namespace model { | |
| return getImpl<detail::CoilSystemCoolingWater_Impl>()->availabilitySchedule(); | ||
| } | ||
|
|
||
| WaterToAirComponent CoilSystemCoolingWater::coolingCoil() const { | ||
| HVACComponent CoilSystemCoolingWater::coolingCoil() const { | ||
| return getImpl<detail::CoilSystemCoolingWater_Impl>()->coolingCoil(); | ||
| } | ||
|
|
||
|
|
@@ -400,15 +391,15 @@ namespace model { | |
| return getImpl<detail::CoilSystemCoolingWater_Impl>()->minimumWaterLoopTemperatureForHeatRecovery(); | ||
| } | ||
|
|
||
| boost::optional<WaterToAirComponent> CoilSystemCoolingWater::companionCoilUsedForHeatRecovery() const { | ||
| boost::optional<HVACComponent> CoilSystemCoolingWater::companionCoilUsedForHeatRecovery() const { | ||
| return getImpl<detail::CoilSystemCoolingWater_Impl>()->companionCoilUsedForHeatRecovery(); | ||
| } | ||
|
|
||
| bool CoilSystemCoolingWater::setAvailabilitySchedule(Schedule& schedule) { | ||
| return getImpl<detail::CoilSystemCoolingWater_Impl>()->setAvailabilitySchedule(schedule); | ||
| } | ||
|
|
||
| bool CoilSystemCoolingWater::setCoolingCoil(const WaterToAirComponent& coolingCoil) { | ||
| bool CoilSystemCoolingWater::setCoolingCoil(const HVACComponent& coolingCoil) { | ||
| return getImpl<detail::CoilSystemCoolingWater_Impl>()->setCoolingCoil(coolingCoil); | ||
| } | ||
|
|
||
|
|
@@ -436,7 +427,7 @@ namespace model { | |
| return getImpl<detail::CoilSystemCoolingWater_Impl>()->setMinimumWaterLoopTemperatureForHeatRecovery(minimumWaterLoopTemperatureForHeatRecovery); | ||
| } | ||
|
|
||
| bool CoilSystemCoolingWater::setCompanionCoilUsedForHeatRecovery(const WaterToAirComponent& companionCoilUsedForHeatRecovery) { | ||
| bool CoilSystemCoolingWater::setCompanionCoilUsedForHeatRecovery(const HVACComponent& companionCoilUsedForHeatRecovery) { | ||
| return getImpl<detail::CoilSystemCoolingWater_Impl>()->setCompanionCoilUsedForHeatRecovery(companionCoilUsedForHeatRecovery); | ||
| } | ||
|
|
||
|
|
||
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 improved the testing for the cases you wrote, and I added a new one for CoilSystem_Cooling_Water_HeatExchangerAssisted