diff --git a/developer/ruby/GenerateClass.rb b/developer/ruby/GenerateClass.rb index ded8f07c81..44c9f238f8 100644 --- a/developer/ruby/GenerateClass.rb +++ b/developer/ruby/GenerateClass.rb @@ -365,7 +365,7 @@ def forwardTranslate(options) # VIRTUAL DESTRUCTORS -hpp << " virtual ~" << className << "() {}\n\n" +hpp << " virtual ~" << className << "() = default;\n\n" hpp << " //@}\n\n" if pImpl diff --git a/developer/ruby/SubProjectClassGenerators/SubProjectClassGenerator.rb b/developer/ruby/SubProjectClassGenerators/SubProjectClassGenerator.rb index 47433a03a7..703f30d894 100644 --- a/developer/ruby/SubProjectClassGenerators/SubProjectClassGenerator.rb +++ b/developer/ruby/SubProjectClassGenerators/SubProjectClassGenerator.rb @@ -220,7 +220,7 @@ def cppPublicClassProtectedImpl() if @baseClassName.empty? result << " : m_impl(impl)\n" else - result << " : " << baseClassName << "(impl)\n" + result << " : " << baseClassName << "(std::move(impl))\n" end result << "{}\n" end diff --git a/resources/energyplus/ProposedEnergy+.idd b/resources/energyplus/ProposedEnergy+.idd index 0047118a5b..00a56b4725 100644 --- a/resources/energyplus/ProposedEnergy+.idd +++ b/resources/energyplus/ProposedEnergy+.idd @@ -9703,6 +9703,28 @@ SurfaceProperty:SolarIncidentInside, \type object-list \object-list ScheduleNames +SurfaceProperty:IncidentSolarMultiplier, + \min-fields 3 + A1, \field Surface Name + \required-field + \type object-list + \object-list GlazedExtSubSurfNames + \note Enter the name of an exterior window outside surface object + N1, \field Incident Solar Multiplier + \note a constant multiplier for window solar transmittance + \note and visible transmittance. If the Shading Multiplier Schedule Name is + \note defined, the product of these two will be the final shading multiplier. + \type real + \units dimensionless + \minimum 0 + \maximum 1 + \default 1.0 + A2; \field Incident Solar Multiplier Schedule Name + \note The schedule values should be greater than or equal + \note to 0 and less than or equal to 1. + \type object-list + \object-list ScheduleNames + SurfaceProperty:LocalEnvironment, \min-fields 3 \memo This object defines the local environment properties of an exterior surface. @@ -9789,6 +9811,33 @@ SurfaceProperty:SurroundingSurfaces, \object-list ScheduleNames \note Schedule values are real numbers, -100.0 to 100.0, units C +SurfaceProperty:GroundSurfaces, + \min-fields 3 + \memo This object defines a list of ground surfaces for use with an exterior surface. + \extensible:4 -- duplicate last set of ground surface properties (the last four fields), remembering to remove ; from "inner" fields. + A1, \field Name + \required-field + \type alpha + \reference GroundSurfacesNames + A2, \field Ground Surface 1 Name + \begin-extensible + \required-field + \type alpha + N1, \field Ground Surface 1 View Factor + \type real + \units dimensionless + \minimum 0.0 + \maximum 1.0 + A3, \field Ground Surface 1 Temperature Schedule Name + \type alpha + \type object-list + \object-list ScheduleNames + \note Schedule values are real numbers, -100.0 to 100.0, units C + A4; \field Ground Surface 1 Reflectance Schedule Name + \type object-list + \object-list ScheduleNames + \note Schedule values are fraction, 0.0 to 1.0, units dimensionless + ComplexFenestrationProperty:SolarAbsorbedLayers, \memo Used to provide solar radiation absorbed in fenestration layers. References surface-construction pair \memo and if that pair is used in a simulation, then program will use value provided in schedules instead of calculating it. diff --git a/resources/model/OpenStudio.idd b/resources/model/OpenStudio.idd index 1dc138092d..06dc8180b9 100644 --- a/resources/model/OpenStudio.idd +++ b/resources/model/OpenStudio.idd @@ -6697,7 +6697,7 @@ OS:SurfaceProperty:SurroundingSurfaces, \type object-list \object-list ScheduleNames \note Schedule values are real numbers, -100.0 to 100.0, units C - \note If the field is left blank the global sky temperature is be used + \note If the field is left blank the global sky temperature is used N2, \field Ground View Factor \minimum 0.0 \maximum 1.0 @@ -6747,10 +6747,68 @@ OS:SurfaceProperty:LocalEnvironment, \type object-list \object-list SurroundingSurfacesNames \note Enter the name of a SurfaceProperty:SurroundingSurfaces object - A6; \field Outdoor Air Node Name + A6, \field Outdoor Air Node Name \type object-list \object-list OutdoorAirNodeNames \note Enter the name of an OutdoorAir:Node object + A7; \field Ground Surfaces Object Name + \type object-list + \object-list GroundSurfacesNames + +OS:SurfaceProperty:GroundSurfaces, + \min-fields 4 + \memo This object defines a list of ground surfaces for use with an exterior surface. + \extensible:4 -- duplicate last set of ground surface properties (the last four fields), remembering to remove ; from "inner" fields. + A1, \field Handle + \type handle + \required-field + A2, \field Name + \required-field + \type alpha + \reference GroundSurfacesNames + A3, \field Ground Surface 1 Name + \begin-extensible + \required-field + \type alpha + N1, \field Ground Surface 1 View Factor + \type real + \units dimensionless + \minimum 0.0 + \maximum 1.0 + \autocalculatable + A4, \field Ground Surface 1 Temperature Schedule Name + \type object-list + \object-list ScheduleNames + \note Schedule values are real numbers, -100.0 to 100.0, units C + A5; \field Ground Surface 1 Reflectance Schedule Name + \type object-list + \object-list ScheduleNames + \note Schedule values are fraction, 0.0 to 1.0, units dimensionless + +OS:SurfaceProperty:IncidentSolarMultiplier, + \min-fields 4 + A1, \field Handle + \type handle + \required-field + A2, \field Surface Name + \required-field + \type object-list + \object-list GlazedExtSubSurfNames + \note Enter the name of an exterior window outside surface object + N1, \field Incident Solar Multiplier + \note a constant multiplier for window solar transmittance + \note and visible transmittance. If the Shading Multiplier Schedule Name is + \note defined, the product of these two will be the final shading multiplier. + \type real + \units dimensionless + \minimum 0 + \maximum 1 + \required-field + A3; \field Incident Solar Multiplier Schedule Name + \note The schedule values should be greater than or equal + \note to 0 and less than or equal to 1. + \type object-list + \object-list ScheduleNames \group OpenStudio Space Loads diff --git a/src/energyplus/CMakeLists.txt b/src/energyplus/CMakeLists.txt index 54fa411346..39f2dd9788 100644 --- a/src/energyplus/CMakeLists.txt +++ b/src/energyplus/CMakeLists.txt @@ -388,6 +388,8 @@ set(${target_name}_src ForwardTranslator/ForwardTranslateSurfacePropertyOtherSideCoefficients.cpp ForwardTranslator/ForwardTranslateSurfacePropertyOtherSideConditionsModel.cpp ForwardTranslator/ForwardTranslateSurfacePropertySurroundingSurfaces.cpp + ForwardTranslator/ForwardTranslateSurfacePropertyGroundSurfaces.cpp + ForwardTranslator/ForwardTranslateSurfacePropertyIncidentSolarMultiplier.cpp ForwardTranslator/ForwardTranslateSwimmingPoolIndoor.cpp ForwardTranslator/ForwardTranslateTableMultiVariableLookup.cpp ForwardTranslator/ForwardTranslateTableLookup.cpp @@ -588,6 +590,8 @@ set(${target_name}_src ReverseTranslator/ReverseTranslateSurfacePropertyExposedFoundationPerimeter.cpp ReverseTranslator/ReverseTranslateSurfacePropertyLocalEnvironment.cpp ReverseTranslator/ReverseTranslateSurfacePropertySurroundingSurfaces.cpp + ReverseTranslator/ReverseTranslateSurfacePropertyGroundSurfaces.cpp + ReverseTranslator/ReverseTranslateSurfacePropertyIncidentSolarMultiplier.cpp ReverseTranslator/ReverseTranslateSwimmingPoolIndoor.cpp ReverseTranslator/ReverseTranslateTableLookup.cpp ReverseTranslator/ReverseTranslateTableIndependentVariable.cpp @@ -761,6 +765,8 @@ set(${target_name}_test_src Test/SurfacePropertyConvectionCoefficients_GTest.cpp Test/SurfacePropertyLocalEnvironment_GTest.cpp Test/SurfacePropertySurroundingSurfaces_GTest.cpp + Test/SurfacePropertyGroundSurfaces_GTest.cpp + Test/SurfacePropertyIncidentSolarMultiplier_GTest.cpp Test/SwimmingPoolIndoor_GTest.cpp Test/TableMultiVariableLookup_GTest.cpp Test/TableLookup_GTest.cpp diff --git a/src/energyplus/ForwardTranslator.cpp b/src/energyplus/ForwardTranslator.cpp index 2f59ccfdee..3c4855de9b 100644 --- a/src/energyplus/ForwardTranslator.cpp +++ b/src/energyplus/ForwardTranslator.cpp @@ -2853,6 +2853,16 @@ namespace energyplus { retVal = translateSurfacePropertySurroundingSurfaces(obj); break; } + case openstudio::IddObjectType::OS_SurfaceProperty_GroundSurfaces: { + model::SurfacePropertyGroundSurfaces obj = modelObject.cast(); + retVal = translateSurfacePropertyGroundSurfaces(obj); + break; + } + case openstudio::IddObjectType::OS_SurfaceProperty_IncidentSolarMultiplier: { + model::SurfacePropertyIncidentSolarMultiplier obj = modelObject.cast(); + retVal = translateSurfacePropertyIncidentSolarMultiplier(obj); + break; + } case openstudio::IddObjectType::OS_SubSurface: { model::SubSurface subSurface = modelObject.cast(); retVal = translateSubSurface(subSurface); diff --git a/src/energyplus/ForwardTranslator.hpp b/src/energyplus/ForwardTranslator.hpp index a4dec8adb6..0ad5dc5302 100644 --- a/src/energyplus/ForwardTranslator.hpp +++ b/src/energyplus/ForwardTranslator.hpp @@ -448,6 +448,8 @@ namespace model { class SurfacePropertyOtherSideCoefficients; class SurfacePropertyOtherSideConditionsModel; class SurfacePropertySurroundingSurfaces; + class SurfacePropertyGroundSurfaces; + class SurfacePropertyIncidentSolarMultiplier; class SwimmingPoolIndoor; class TableMultiVariableLookup; class TableLookup; @@ -1428,6 +1430,10 @@ namespace energyplus { boost::optional translateSurfacePropertySurroundingSurfaces(model::SurfacePropertySurroundingSurfaces& modelObject); + boost::optional translateSurfacePropertyGroundSurfaces(model::SurfacePropertyGroundSurfaces& modelObject); + + boost::optional translateSurfacePropertyIncidentSolarMultiplier(model::SurfacePropertyIncidentSolarMultiplier& modelObject); + boost::optional translateSwimmingPoolIndoor(model::SwimmingPoolIndoor& modelObject); OS_DEPRECATED boost::optional translateTableMultiVariableLookup(model::TableMultiVariableLookup& modelObject); diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateSubSurface.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateSubSurface.cpp index beb9a389b4..6aeef3058f 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateSubSurface.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateSubSurface.cpp @@ -42,6 +42,7 @@ #include "../../model/SurfacePropertyOtherSideConditionsModel.hpp" #include "../../model/SurfacePropertyConvectionCoefficients.hpp" #include "../../model/SurfacePropertyLocalEnvironment.hpp" +#include "../../model/SurfacePropertyIncidentSolarMultiplier.hpp" #include "../../utilities/idf/IdfExtensibleGroup.hpp" @@ -66,10 +67,31 @@ namespace energyplus { idfObject.setString(FenestrationSurface_DetailedFields::Name, modelObject.name().get()); + openstudio::Vector3d offset(0, 0, 0); + idfObject.clearExtensibleGroups(); + for (const Point3d& point : modelObject.vertices()) { + IdfExtensibleGroup group = idfObject.pushExtensibleGroup(); + if (group.empty()) { + LOG(Error, + "Currently unable to translate " << modelObject.briefDescription() << ", because it has more vertices than allowed by EnergyPlus."); + return boost::none; + } + + Point3d newPoint = point + offset; + + group.setDouble(0, newPoint.x()); + group.setDouble(1, newPoint.y()); + group.setDouble(2, newPoint.z()); + } + + // Register and emplace into m_map, so that any child object such as translateSurfacePropertyIncidentSolarMultiplier + // can retrieve the subsurface namestring and we don't risk duplicating the subsurface when that child also calls + // translateAndMapModelObject(subSurface) + m_idfObjects.push_back(idfObject); + m_map.insert(std::make_pair(modelObject.handle(), idfObject)); + std::string subSurfaceType = modelObject.subSurfaceType(); - if (istringEqual("FixedWindow", subSurfaceType)) { - subSurfaceType = "Window"; - } else if (istringEqual("OperableWindow", subSurfaceType)) { + if (istringEqual("FixedWindow", subSurfaceType) || istringEqual("OperableWindow", subSurfaceType)) { subSurfaceType = "Window"; } else if (istringEqual("OverheadDoor", subSurfaceType)) { subSurfaceType = "Door"; @@ -140,7 +162,6 @@ namespace energyplus { } boost::optional frameAndDivider = modelObject.windowPropertyFrameAndDivider(); - openstudio::Vector3d offset(0, 0, 0); if (frameAndDivider) { if (!frameAndDivider->isOutsideRevealDepthDefaulted()) { offset = -frameAndDivider->outsideRevealDepth() * modelObject.outwardNormal(); @@ -152,24 +173,10 @@ namespace energyplus { idfObject.setDouble(FenestrationSurface_DetailedFields::Multiplier, modelObject.multiplier()); } - idfObject.clearExtensibleGroups(); - for (const Point3d& point : modelObject.vertices()) { - IdfExtensibleGroup group = idfObject.pushExtensibleGroup(); - if (group.empty()) { - LOG(Error, - "Currently unable to translate " << modelObject.briefDescription() << ", because it has more vertices than allowed by EnergyPlus."); - return boost::none; - } - - Point3d newPoint = point + offset; - - group.setDouble(0, newPoint.x()); - group.setDouble(1, newPoint.y()); - group.setDouble(2, newPoint.z()); + if (boost::optional spMult_ = modelObject.surfacePropertyIncidentSolarMultiplier()) { + translateAndMapModelObject(spMult_.get()); } - m_idfObjects.push_back(idfObject); - return idfObject; } diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateSurfacePropertyGroundSurfaces.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateSurfacePropertyGroundSurfaces.cpp new file mode 100644 index 0000000000..a77879e772 --- /dev/null +++ b/src/energyplus/ForwardTranslator/ForwardTranslateSurfacePropertyGroundSurfaces.cpp @@ -0,0 +1,75 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +* following conditions are met: +* +* (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following +* disclaimer. +* +* (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided with the distribution. +* +* (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products +* derived from this software without specific prior written permission from the respective party. +* +* (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works +* may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior +* written permission from Alliance for Sustainable Energy, LLC. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED +* STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +***********************************************************************************************************************/ + +#include "../ForwardTranslator.hpp" +#include "../../model/Model.hpp" + +#include "../../model/SurfacePropertyGroundSurfaces.hpp" +#include "../../model/Schedule.hpp" + +#include "../../utilities/idf/IdfExtensibleGroup.hpp" + +#include +// #include "../../utilities/idd/IddEnums.hpp" +#include + +using namespace openstudio::model; + +namespace openstudio { + +namespace energyplus { + + boost::optional ForwardTranslator::translateSurfacePropertyGroundSurfaces(model::SurfacePropertyGroundSurfaces& modelObject) { + boost::optional result; + + // Instantiate an IdfObject of the class to store the values + IdfObject idfObject = createRegisterAndNameIdfObject(openstudio::IddObjectType::SurfaceProperty_GroundSurfaces, modelObject); + + for (const auto& group : modelObject.groundSurfaceGroups()) { + + IdfExtensibleGroup eg = idfObject.pushExtensibleGroup(); + eg.setString(SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceName, group.groundSurfaceName()); + eg.setDouble(SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceViewFactor, group.viewFactor()); + if (auto sch_ = group.temperatureSchedule()) { + if (boost::optional _owo = translateAndMapModelObject(sch_.get())) { + eg.setString(SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceTemperatureScheduleName, _owo->nameString()); + } // TODO: handle failure? + } + if (auto sch_ = group.reflectanceSchedule()) { + if (boost::optional _owo = translateAndMapModelObject(sch_.get())) { + eg.setString(SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceReflectanceScheduleName, _owo->nameString()); + } // TODO: handle failure? + } + } + + return idfObject; + } // End of translate function + +} // end namespace energyplus +} // end namespace openstudio diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateSurfacePropertyIncidentSolarMultiplier.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateSurfacePropertyIncidentSolarMultiplier.cpp new file mode 100644 index 0000000000..5cb27b7689 --- /dev/null +++ b/src/energyplus/ForwardTranslator/ForwardTranslateSurfacePropertyIncidentSolarMultiplier.cpp @@ -0,0 +1,77 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +* following conditions are met: +* +* (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following +* disclaimer. +* +* (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided with the distribution. +* +* (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products +* derived from this software without specific prior written permission from the respective party. +* +* (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works +* may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior +* written permission from Alliance for Sustainable Energy, LLC. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED +* STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +***********************************************************************************************************************/ + +#include "../ForwardTranslator.hpp" +#include "../../model/Model.hpp" + +#include "../../model/SurfacePropertyIncidentSolarMultiplier.hpp" + +#include "../../model/SubSurface.hpp" +#include "../../model/SubSurface_Impl.hpp" + +#include "../../model/Schedule.hpp" +#include "../../model/Schedule_Impl.hpp" + +#include +// #include "../../utilities/idd/IddEnums.hpp" +#include + +using namespace openstudio::model; + +namespace openstudio { + +namespace energyplus { + + boost::optional + ForwardTranslator::translateSurfacePropertyIncidentSolarMultiplier(model::SurfacePropertyIncidentSolarMultiplier& modelObject) { + + // Instantiate an IdfObject of the class to store the values + IdfObject idfObject = createAndRegisterIdfObject(openstudio::IddObjectType::SurfaceProperty_IncidentSolarMultiplier, modelObject); + + // Surface Name: Required Object + SubSurface subSurface = modelObject.subSurface(); + if (boost::optional _owo = translateAndMapModelObject(subSurface)) { + idfObject.setString(SurfaceProperty_IncidentSolarMultiplierFields::SurfaceName, _owo->nameString()); + } + + // Incident Solar Multiplier: Optional Double + idfObject.setDouble(SurfaceProperty_IncidentSolarMultiplierFields::IncidentSolarMultiplier, modelObject.incidentSolarMultiplier()); + + // Incident Solar Multiplier Schedule Name: Optional Object + if (boost::optional _incidentSolarMultiplierSchedule = modelObject.incidentSolarMultiplierSchedule()) { + if (boost::optional _owo = translateAndMapModelObject(_incidentSolarMultiplierSchedule.get())) { + idfObject.setString(SurfaceProperty_IncidentSolarMultiplierFields::IncidentSolarMultiplierScheduleName, _owo->nameString()); + } + } + + return idfObject; + } // End of translate function + +} // end namespace energyplus +} // end namespace openstudio diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateSurfacePropertyLocalEnvironment.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateSurfacePropertyLocalEnvironment.cpp index 9ef79f54c4..859baba6a7 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateSurfacePropertyLocalEnvironment.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateSurfacePropertyLocalEnvironment.cpp @@ -35,7 +35,7 @@ #include "../../model/PlanarSurface.hpp" #include "../../model/SurfacePropertySurroundingSurfaces.hpp" -#include "../../model/SurfacePropertySurroundingSurfaces_Impl.hpp" +#include "../../model/SurfacePropertyGroundSurfaces.hpp" //#include "../../model/OutdoorAirNode.hpp" //#include "../../model/OutdoorAirNode_Impl.hpp" @@ -75,6 +75,13 @@ namespace energyplus { } } + // Ground Surfaces Object Name: Optional Object + if (boost::optional sp_ = modelObject.surfacePropertyGroundSurfaces()) { + if (boost::optional _owo = translateAndMapModelObject(sp_.get())) { + idfObject.setString(SurfaceProperty_LocalEnvironmentFields::GroundSurfacesObjectName, _owo->nameString()); + } + } + // Outdoor Air Node Name: Optional Object // if (boost::optional _outdoorAirNode = modelObject.outdoorAirNode()) { // if (boost::optional _owo = translateAndMapModelObject(_outdoorAirNode.get())) { diff --git a/src/energyplus/ReverseTranslator.cpp b/src/energyplus/ReverseTranslator.cpp index 4c52b3c741..9d3ef0e899 100644 --- a/src/energyplus/ReverseTranslator.cpp +++ b/src/energyplus/ReverseTranslator.cpp @@ -903,6 +903,14 @@ namespace energyplus { case openstudio::IddObjectType::SurfaceProperty_SurroundingSurfaces: { modelObject = translateSurfacePropertySurroundingSurfaces(workspaceObject); break; + } + case openstudio::IddObjectType::SurfaceProperty_GroundSurfaces: { + modelObject = translateSurfacePropertyGroundSurfaces(workspaceObject); + break; + } + case openstudio::IddObjectType::SurfaceProperty_IncidentSolarMultiplier: { + modelObject = translateSurfacePropertyIncidentSolarMultiplier(workspaceObject); + break; } //case openstudio::IddObjectType::SwimmingPool_Indoor : //{ diff --git a/src/energyplus/ReverseTranslator.hpp b/src/energyplus/ReverseTranslator.hpp index afde8e5570..73bbda6606 100644 --- a/src/energyplus/ReverseTranslator.hpp +++ b/src/energyplus/ReverseTranslator.hpp @@ -363,6 +363,10 @@ namespace energyplus { boost::optional translateSurfacePropertySurroundingSurfaces(const WorkspaceObject& workspaceObject); + boost::optional translateSurfacePropertyGroundSurfaces(const WorkspaceObject& workspaceObject); + + boost::optional translateSurfacePropertyIncidentSolarMultiplier(const WorkspaceObject& workspaceObject); + boost::optional translateSwimmingPoolIndoor(const WorkspaceObject& workspaceObject); boost::optional translateTableLookup(const WorkspaceObject& workspaceObject); diff --git a/src/energyplus/ReverseTranslator/ReverseTranslateSurfacePropertyGroundSurfaces.cpp b/src/energyplus/ReverseTranslator/ReverseTranslateSurfacePropertyGroundSurfaces.cpp new file mode 100644 index 0000000000..ead8611102 --- /dev/null +++ b/src/energyplus/ReverseTranslator/ReverseTranslateSurfacePropertyGroundSurfaces.cpp @@ -0,0 +1,107 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +* following conditions are met: +* +* (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following +* disclaimer. +* +* (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided with the distribution. +* +* (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products +* derived from this software without specific prior written permission from the respective party. +* +* (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works +* may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior +* written permission from Alliance for Sustainable Energy, LLC. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED +* STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +***********************************************************************************************************************/ + +#include "../ReverseTranslator.hpp" + +#include "../../model/SurfacePropertyGroundSurfaces.hpp" +#include "../../model/Schedule.hpp" +#include "../../model/Schedule_Impl.hpp" + +#include "../../utilities/idf/IdfExtensibleGroup.hpp" +#include "../../utilities/idf/WorkspaceExtensibleGroup.hpp" + +#include +#include + +using namespace openstudio::model; + +namespace openstudio { + +namespace energyplus { + + boost::optional ReverseTranslator::translateSurfacePropertyGroundSurfaces(const WorkspaceObject& workspaceObject) { + + // Instantiate an object of the class to store the values, + openstudio::model::SurfacePropertyGroundSurfaces modelObject(m_model); + + // Name + if (boost::optional _name = workspaceObject.name()) { + modelObject.setName(_name.get()); + } + + // Extensible groups + for (const IdfExtensibleGroup& eg : workspaceObject.extensibleGroups()) { + auto weg = eg.cast(); + + auto groundSurfaceName = weg.getString(SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceName).get(); + if (groundSurfaceName.empty()) { + LOG(Warn, "Extensible group " << eg.groupIndex() << "(0-indexed) has an empty Ground Surface Name field, skipping group"); + continue; + } + + // This has a default of 0, so roll with it + auto viewFactor = weg.getDouble(SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceViewFactor).get(); + + boost::optional tempSch_; + boost::optional refSch_; + + if (auto wo_ = weg.getTarget(SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceTemperatureScheduleName)) { + if (auto mo_ = translateAndMapWorkspaceObject(wo_.get())) { + if (boost::optional sch_ = mo_->optionalCast()) { + tempSch_ = sch_; + } else { + LOG(Warn, "Extensible group " << eg.groupIndex() << "(0-indexed) has a wrong type for Temperature Schedule, expected Schedule, got " + << tempSch_->briefDescription()); + } + } else { + LOG(Warn, "Could not translate Temperature Schedule for Extensible group " << eg.groupIndex()); + } + } + + if (auto wo_ = weg.getTarget(SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceReflectanceScheduleName)) { + if (auto mo_ = translateAndMapWorkspaceObject(wo_.get())) { + if (boost::optional sch_ = mo_->optionalCast()) { + refSch_ = sch_; + } else { + LOG(Warn, "Extensible group " << eg.groupIndex() << "(0-indexed) has a wrong type for Reflectance Schedule, expected Schedule, got " + << tempSch_->briefDescription()); + } + } else { + LOG(Warn, "Could not translate Reflectance Schedule for Extensible group " << eg.groupIndex()); + } + } + + modelObject.addGroundSurfaceGroup(groundSurfaceName, viewFactor, tempSch_, refSch_); + } + + return modelObject; + } // End of translate function + +} // end namespace energyplus +} // end namespace openstudio diff --git a/src/energyplus/ReverseTranslator/ReverseTranslateSurfacePropertyIncidentSolarMultiplier.cpp b/src/energyplus/ReverseTranslator/ReverseTranslateSurfacePropertyIncidentSolarMultiplier.cpp new file mode 100644 index 0000000000..bcb4029ddb --- /dev/null +++ b/src/energyplus/ReverseTranslator/ReverseTranslateSurfacePropertyIncidentSolarMultiplier.cpp @@ -0,0 +1,95 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +* following conditions are met: +* +* (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following +* disclaimer. +* +* (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided with the distribution. +* +* (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products +* derived from this software without specific prior written permission from the respective party. +* +* (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works +* may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior +* written permission from Alliance for Sustainable Energy, LLC. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED +* STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +***********************************************************************************************************************/ + +#include "../ReverseTranslator.hpp" + +#include "../../model/SurfacePropertyIncidentSolarMultiplier.hpp" + +#include "../../model/SubSurface.hpp" +#include "../../model/SubSurface_Impl.hpp" + +#include "../../model/Schedule.hpp" +#include "../../model/Schedule_Impl.hpp" + +#include +#include + +using namespace openstudio::model; + +namespace openstudio { + +namespace energyplus { + + boost::optional ReverseTranslator::translateSurfacePropertyIncidentSolarMultiplier(const WorkspaceObject& workspaceObject) { + + boost::optional subSurface_; + + // Surface Name: Required Object + if (auto wo_ = workspaceObject.getTarget(SurfaceProperty_IncidentSolarMultiplierFields::SurfaceName)) { + if (auto mo_ = translateAndMapWorkspaceObject(wo_.get())) { + + if (auto ss_ = mo_->optionalCast()) { + subSurface_ = ss_; + } else { + LOG(Warn, workspaceObject.briefDescription() << " has a wrong type for 'Surface Name', cannot reverse translate."); + return boost::none; + } + } else { + LOG(Error, "For " << workspaceObject.briefDescription() << ", cannot reverse translate required object 'Surface Name'"); + return boost::none; + } + } else { + LOG(Error, "For " << workspaceObject.briefDescription() << ", cannot find required object 'Surface Name'"); + return boost::none; + } + + openstudio::model::SurfacePropertyIncidentSolarMultiplier modelObject(subSurface_.get()); + + // Incident Solar Multiplier: Optional Double + if (boost::optional _incidentSolarMultiplier = + workspaceObject.getDouble(SurfaceProperty_IncidentSolarMultiplierFields::IncidentSolarMultiplier)) { + modelObject.setIncidentSolarMultiplier(_incidentSolarMultiplier.get()); + } + + // Incident Solar Multiplier Schedule Name: Optional Object + if (auto wo_ = workspaceObject.getTarget(SurfaceProperty_IncidentSolarMultiplierFields::IncidentSolarMultiplierScheduleName)) { + if (auto mo_ = translateAndMapWorkspaceObject(wo_.get())) { + if (boost::optional _incidentSolarMultiplierSchedule = mo_->optionalCast()) { + modelObject.setIncidentSolarMultiplierSchedule(_incidentSolarMultiplierSchedule.get()); + } else { + LOG(Warn, workspaceObject.briefDescription() << " has a wrong type for 'Incident Solar Multiplier Schedule Name'"); + } + } + } + + return modelObject; + } // End of translate function + +} // end namespace energyplus +} // end namespace openstudio diff --git a/src/energyplus/Test/SurfacePropertyGroundSurfaces_GTest.cpp b/src/energyplus/Test/SurfacePropertyGroundSurfaces_GTest.cpp new file mode 100644 index 0000000000..7e4b11a9c7 --- /dev/null +++ b/src/energyplus/Test/SurfacePropertyGroundSurfaces_GTest.cpp @@ -0,0 +1,239 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +* following conditions are met: +* +* (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following +* disclaimer. +* +* (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided with the distribution. +* +* (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products +* derived from this software without specific prior written permission from the respective party. +* +* (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works +* may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior +* written permission from Alliance for Sustainable Energy, LLC. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED +* STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +***********************************************************************************************************************/ + +#include +#include "EnergyPlusFixture.hpp" + +#include "../ErrorFile.hpp" +#include "../ForwardTranslator.hpp" +#include "../ReverseTranslator.hpp" + +#include "../../model/Model.hpp" +#include "../../model/ThermalZone.hpp" +#include "../../model/Space.hpp" +#include "../../model/SurfacePropertyLocalEnvironment.hpp" +#include "../../model/SurfacePropertyGroundSurfaces.hpp" +#include "../../model/SurfacePropertyGroundSurfaces_Impl.hpp" +#include "../../model/ScheduleConstant.hpp" +#include "../../model/Surface.hpp" +#include "../../model/Surface_Impl.hpp" +#include "../../model/SubSurface.hpp" + +#include "../../utilities/idf/WorkspaceObject.hpp" +#include "../../utilities/geometry/Point3d.hpp" +#include "../../utilities/idf/IdfExtensibleGroup.hpp" +#include "../../utilities/idf/WorkspaceExtensibleGroup.hpp" + +#include +#include +#include +#include +#include + +#include + +using namespace openstudio::energyplus; +using namespace openstudio::model; +using namespace openstudio; + +TEST_F(EnergyPlusFixture, ForwardTranslator_SurfacePropertyGroundSurfaces) { + + ForwardTranslator ft; + + // Zone translates Space, Space translates Surface, Surface translates its LocalEnv object, and this in turns translates our + Model m; + ThermalZone tz(m); + Space space(m); + EXPECT_TRUE(space.setThermalZone(tz)); + + std::vector sPoints{ + {0, 2, 0}, + {0, 0, 0}, + {2, 0, 0}, + {2, 2, 0}, + }; + Surface surface(sPoints, m); + surface.setSpace(space); + + SurfacePropertyGroundSurfaces sp(m); + sp.setName("SurfaceProperty Ground Surfaces"); + + // Not assigned to a LocalEnv? not translate + { + // Assigned to a Surface + Workspace w = ft.translateModel(m); + + EXPECT_EQ(0, w.getObjectsByType(IddObjectType::SurfaceProperty_LocalEnvironment).size()); + EXPECT_EQ(0, w.getObjectsByType(IddObjectType::SurfaceProperty_GroundSurfaces).size()); + } + + SurfacePropertyLocalEnvironment localEnv(surface); + localEnv.setName(surface.nameString() + " LocalEnv"); + EXPECT_TRUE(localEnv.setSurfacePropertyGroundSurfaces(sp)); + ASSERT_TRUE(localEnv.surfacePropertyGroundSurfaces()); + EXPECT_EQ(sp, localEnv.surfacePropertyGroundSurfaces().get()); + + // Create 5 groups + for (int i = 1; i <= 5; ++i) { + ScheduleConstant tempSch(m); + tempSch.setName("tempSch" + std::to_string(i)); + + ScheduleConstant reflectanceSch(m); + reflectanceSch.setName("reflectanceSch" + std::to_string(i)); + + std::string sfName = "External Surface " + std::to_string(i); + double viewFactor = 0.01 * i; + + if (i % 2 == 0) { + EXPECT_TRUE(sp.addGroundSurfaceGroup(sfName, viewFactor, tempSch, boost::none)); + } else { + GroundSurfaceGroup group(sfName, viewFactor, boost::none, reflectanceSch); + EXPECT_TRUE(sp.addGroundSurfaceGroup(group)); + } + EXPECT_EQ(i, sp.numberofGroundSurfaceGroups()); + } + EXPECT_EQ(5, sp.numberofGroundSurfaceGroups()); + + std::vector groups = sp.groundSurfaceGroups(); + + { + // Only assigned the groups here + Workspace w = ft.translateModel(m); + + std::vector woEnvs = w.getObjectsByType(IddObjectType::SurfaceProperty_LocalEnvironment); + ASSERT_EQ(1, woEnvs.size()); + std::vector woSps = w.getObjectsByType(IddObjectType::SurfaceProperty_GroundSurfaces); + ASSERT_EQ(1, woSps.size()); + + auto& wo_localEnv = woEnvs[0]; + EXPECT_EQ(localEnv.nameString(), wo_localEnv.nameString()); + + EXPECT_EQ(sp.nameString(), wo_localEnv.getString(SurfaceProperty_LocalEnvironmentFields::GroundSurfacesObjectName).get()); + auto& woSp = woSps[0]; + EXPECT_EQ(sp.nameString(), woSp.nameString()); + + ASSERT_EQ(5, woSp.numExtensibleGroups()); + for (const auto& idf_eg : woSp.extensibleGroups()) { + auto& group = groups[idf_eg.groupIndex()]; + + EXPECT_EQ(group.groundSurfaceName(), idf_eg.getString(SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceName).get()); + EXPECT_EQ(group.viewFactor(), idf_eg.getDouble(SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceViewFactor).get()); + if ((idf_eg.groupIndex() + 1) % 2 == 0) { + ASSERT_TRUE(group.temperatureSchedule()); + EXPECT_EQ(group.temperatureSchedule()->nameString(), + idf_eg.getString(SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceTemperatureScheduleName).get()); + EXPECT_FALSE(group.reflectanceSchedule()); + } else { + EXPECT_FALSE(group.temperatureSchedule()); + ASSERT_TRUE(group.reflectanceSchedule()); + EXPECT_EQ(group.reflectanceSchedule()->nameString(), + idf_eg.getString(SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceReflectanceScheduleName).get()); + } + } + } +} + +TEST_F(EnergyPlusFixture, ReverseTranslator_SurfacePropertyGroundSurfaces) { + + ReverseTranslator rt; + + Workspace w(StrictnessLevel::Minimal, IddFileType::EnergyPlus); + + auto wo_zone = w.addObject(IdfObject(IddObjectType::Zone)).get(); + wo_zone.setName("Thermal Zone 1"); + + auto wo_sp = w.addObject(IdfObject(IddObjectType::SurfaceProperty_GroundSurfaces)).get(); + + auto tempSch = w.addObject(IdfObject(IddObjectType::Schedule_Constant)).get(); + tempSch.setName("tempSch1"); + EXPECT_TRUE(tempSch.setDouble(Schedule_ConstantFields::HourlyValue, 13.5)); + + auto reflectanceSch = w.addObject(IdfObject(IddObjectType::Schedule_Constant)).get(); + reflectanceSch.setName("reflectanceSch"); + EXPECT_TRUE(reflectanceSch.setDouble(Schedule_ConstantFields::HourlyValue, 0.9)); + + struct Group + { + Group(std::string s, double v, std::string tempSch, std::string refSch) + : groundSurfaceName(std::move(s)), viewFactor(v), temperatureScheduleName(std::move(tempSch)), reflectanceScheduleName(std::move(refSch)) {} + + std::string groundSurfaceName; + double viewFactor; + std::string temperatureScheduleName; + std::string reflectanceScheduleName; + }; + + std::vector check_groups; + + for (int i = 1; i <= 5; ++i) { + auto w_eg = wo_sp.pushExtensibleGroup().cast(); + std::string sfName = "External Surface " + std::to_string(i); + EXPECT_TRUE(w_eg.setString(SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceName, sfName)); + + double viewFactor = 0.01 * i; + EXPECT_TRUE(w_eg.setDouble(SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceViewFactor, viewFactor)); + + if (i % 2 == 0) { + EXPECT_TRUE(w_eg.setPointer(SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceTemperatureScheduleName, tempSch.handle())); + check_groups.emplace_back(sfName, viewFactor, tempSch.nameString(), ""); + } else { + EXPECT_TRUE(w_eg.setPointer(SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceReflectanceScheduleName, reflectanceSch.handle())); + check_groups.emplace_back(sfName, viewFactor, "", reflectanceSch.nameString()); + } + } + + Model m = rt.translateWorkspace(w); + + auto sps = m.getConcreteModelObjects(); + ASSERT_EQ(1, sps.size()); + auto& sp = sps[0]; + + ASSERT_EQ(5, sp.numberofGroundSurfaceGroups()); + auto groups = sp.groundSurfaceGroups(); + ASSERT_EQ(5, groups.size()); + + for (size_t i = 0; i < 5; ++i) { + auto& group = groups[i]; + auto& check_group = check_groups[i]; + EXPECT_EQ(check_group.groundSurfaceName, group.groundSurfaceName()); + EXPECT_EQ(check_group.viewFactor, group.viewFactor()); + if (!check_group.temperatureScheduleName.empty()) { + ASSERT_TRUE(group.temperatureSchedule()); + EXPECT_EQ(check_group.temperatureScheduleName, group.temperatureSchedule()->nameString()); + } else { + EXPECT_FALSE(group.temperatureSchedule()); + } + if (!check_group.reflectanceScheduleName.empty()) { + ASSERT_TRUE(group.reflectanceSchedule()); + EXPECT_EQ(check_group.reflectanceScheduleName, group.reflectanceSchedule()->nameString()); + } else { + EXPECT_FALSE(group.reflectanceSchedule()); + } + } +} diff --git a/src/energyplus/Test/SurfacePropertyIncidentSolarMultiplier_GTest.cpp b/src/energyplus/Test/SurfacePropertyIncidentSolarMultiplier_GTest.cpp new file mode 100644 index 0000000000..713a7159e6 --- /dev/null +++ b/src/energyplus/Test/SurfacePropertyIncidentSolarMultiplier_GTest.cpp @@ -0,0 +1,200 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +* following conditions are met: +* +* (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following +* disclaimer. +* +* (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided with the distribution. +* +* (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products +* derived from this software without specific prior written permission from the respective party. +* +* (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works +* may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior +* written permission from Alliance for Sustainable Energy, LLC. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED +* STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +***********************************************************************************************************************/ + +#include +#include "EnergyPlusFixture.hpp" + +#include "../ErrorFile.hpp" +#include "../ForwardTranslator.hpp" +#include "../ReverseTranslator.hpp" + +#include "../../model/Model.hpp" +#include "../../model/ThermalZone.hpp" +#include "../../model/Space.hpp" +#include "../../model/SurfacePropertyIncidentSolarMultiplier.hpp" +#include "../../model/SurfacePropertyIncidentSolarMultiplier_Impl.hpp" +#include "../../model/ScheduleConstant.hpp" +#include "../../model/Surface.hpp" +#include "../../model/Surface_Impl.hpp" +#include "../../model/SubSurface.hpp" +#include "../../model/SubSurface_Impl.hpp" + +#include "../../utilities/idf/WorkspaceObject.hpp" +#include "../../utilities/geometry/Point3d.hpp" +#include "../../utilities/idf/IdfExtensibleGroup.hpp" +#include "../../utilities/idf/WorkspaceExtensibleGroup.hpp" + +#include +#include +#include +#include +#include +#include + +#include + +using namespace openstudio::energyplus; +using namespace openstudio::model; +using namespace openstudio; + +TEST_F(EnergyPlusFixture, ForwardTranslator_SurfacePropertyIncidentSolarMultiplier) { + + ForwardTranslator ft; + + // Zone translates Space, Space translates Surface, Surface translates its LocalEnv object, and this in turns translates our + Model m; + ThermalZone tz(m); + Space space(m); + EXPECT_TRUE(space.setThermalZone(tz)); + + std::vector sPoints{{0, 2, 0}, {0, 0, 0}, {2, 0, 0}, {2, 2, 0}}; + Surface surface(sPoints, m); + surface.setSpace(space); + + std::vector ssPoints{{0, 0, 1}, {0, 0, 0}, {1, 0, 0}, {1, 0, 1}}; + + SubSurface ss(ssPoints, m); + ss.setName("SubSurface1"); + ss.setSurface(surface); + + SurfacePropertyIncidentSolarMultiplier sp(ss); + // Incident Solar Multiplier: Required Double + EXPECT_TRUE(sp.setIncidentSolarMultiplier(0.75)); + + // Incident Solar Multiplier Schedule Name: Optional Object + ScheduleConstant sch(m); + EXPECT_TRUE(sp.setIncidentSolarMultiplierSchedule(sch)); + + // Only assigned the groups here + Workspace w = ft.translateModel(m); + + std::vector woSps = w.getObjectsByType(IddObjectType::SurfaceProperty_IncidentSolarMultiplier); + ASSERT_EQ(1, woSps.size()); + auto& woSp = woSps.front(); + + ASSERT_EQ(1, w.getObjectsByType(IddObjectType::BuildingSurface_Detailed).size()); + ASSERT_EQ(1, w.getObjectsByType(IddObjectType::FenestrationSurface_Detailed).size()); + + EXPECT_EQ(ss.nameString(), woSp.getTarget(SurfaceProperty_IncidentSolarMultiplierFields::SurfaceName)->nameString()); + EXPECT_EQ("SubSurface1", woSp.getTarget(SurfaceProperty_IncidentSolarMultiplierFields::SurfaceName)->nameString()); + EXPECT_EQ(sp.incidentSolarMultiplier(), woSp.getDouble(SurfaceProperty_IncidentSolarMultiplierFields::IncidentSolarMultiplier).get()); + EXPECT_EQ(sch.nameString(), woSp.getString(SurfaceProperty_IncidentSolarMultiplierFields::IncidentSolarMultiplierScheduleName).get()); +} + +TEST_F(EnergyPlusFixture, ReverseTranslator_SurfacePropertyIncidentSolarMultiplier) { + + ReverseTranslator rt; + + Workspace w(StrictnessLevel::Minimal, IddFileType::EnergyPlus); + + auto wo_zone = w.addObject(IdfObject(IddObjectType::Zone)).get(); + wo_zone.setName("Thermal Zone 1"); + + auto wo_sf = w.addObject(IdfObject(IddObjectType::BuildingSurface_Detailed)).get(); + wo_sf.setName("Surface 1"); + EXPECT_TRUE(wo_sf.setString(BuildingSurface_DetailedFields::SurfaceType, "Wall")); + EXPECT_TRUE(wo_sf.setString(BuildingSurface_DetailedFields::ConstructionName, "")); + EXPECT_TRUE(wo_sf.setPointer(BuildingSurface_DetailedFields::ZoneName, wo_zone.handle())); + EXPECT_TRUE(wo_sf.setString(BuildingSurface_DetailedFields::OutsideBoundaryCondition, "Outdoors")); + EXPECT_TRUE(wo_sf.setString(BuildingSurface_DetailedFields::OutsideBoundaryConditionObject, "")); + EXPECT_TRUE(wo_sf.setString(BuildingSurface_DetailedFields::SunExposure, "SunExposed")); + EXPECT_TRUE(wo_sf.setString(BuildingSurface_DetailedFields::WindExposure, "WindExposed")); + EXPECT_TRUE(wo_sf.setString(BuildingSurface_DetailedFields::ViewFactortoGround, "")); + EXPECT_TRUE(wo_sf.setString(BuildingSurface_DetailedFields::NumberofVertices, "")); + { + IdfExtensibleGroup group1 = wo_sf.pushExtensibleGroup(); // vertex 1 + group1.setDouble(0, 0); + group1.setDouble(1, 2); + group1.setDouble(2, 0); + IdfExtensibleGroup group2 = wo_sf.pushExtensibleGroup(); // vertex 2 + group2.setDouble(0, 0); + group2.setDouble(1, 0); + group2.setDouble(2, 0); + IdfExtensibleGroup group3 = wo_sf.pushExtensibleGroup(); // vertex 3 + group3.setDouble(0, 2); + group3.setDouble(1, 0); + group3.setDouble(2, 0); + IdfExtensibleGroup group4 = wo_sf.pushExtensibleGroup(); // vertex 4 + group4.setDouble(0, 2); + group4.setDouble(1, 2); + group4.setDouble(2, 0); + } + + auto wo_ss = w.addObject(IdfObject(IddObjectType::FenestrationSurface_Detailed)).get(); + wo_ss.setName("SubSurface 1"); + EXPECT_TRUE(wo_ss.setString(FenestrationSurface_DetailedFields::SurfaceType, "Window")); + EXPECT_TRUE(wo_ss.setString(FenestrationSurface_DetailedFields::ConstructionName, "")); + EXPECT_TRUE(wo_ss.setPointer(FenestrationSurface_DetailedFields::BuildingSurfaceName, wo_sf.handle())); + EXPECT_TRUE(wo_ss.setString(FenestrationSurface_DetailedFields::OutsideBoundaryConditionObject, "")); + EXPECT_TRUE(wo_ss.setDouble(FenestrationSurface_DetailedFields::ViewFactortoGround, 0.0)); + EXPECT_TRUE(wo_ss.setString(FenestrationSurface_DetailedFields::FrameandDividerName, "")); + EXPECT_TRUE(wo_ss.setDouble(FenestrationSurface_DetailedFields::Multiplier, 0.0)); + EXPECT_TRUE(wo_ss.setDouble(FenestrationSurface_DetailedFields::NumberofVertices, 0.0)); + { + IdfExtensibleGroup group1 = wo_ss.pushExtensibleGroup(); // vertex 1 + group1.setDouble(0, 0); + group1.setDouble(1, 1); + group1.setDouble(2, 0); + IdfExtensibleGroup group2 = wo_ss.pushExtensibleGroup(); // vertex 2 + group2.setDouble(0, 0); + group2.setDouble(1, 0); + group2.setDouble(2, 0); + IdfExtensibleGroup group3 = wo_ss.pushExtensibleGroup(); // vertex 3 + group3.setDouble(0, 1); + group3.setDouble(1, 0); + group3.setDouble(2, 0); + IdfExtensibleGroup group4 = wo_ss.pushExtensibleGroup(); // vertex 4 + group4.setDouble(0, 1); + group4.setDouble(1, 1); + group4.setDouble(2, 0); + } + + auto multSch = w.addObject(IdfObject(IddObjectType::Schedule_Constant)).get(); + multSch.setName("multSch"); + EXPECT_TRUE(multSch.setDouble(Schedule_ConstantFields::HourlyValue, 0.9)); + + auto wo_sp = w.addObject(IdfObject(IddObjectType::SurfaceProperty_IncidentSolarMultiplier)).get(); + + EXPECT_TRUE(wo_sp.setPointer(SurfaceProperty_IncidentSolarMultiplierFields::SurfaceName, wo_ss.handle())); + EXPECT_TRUE(wo_sp.setDouble(SurfaceProperty_IncidentSolarMultiplierFields::IncidentSolarMultiplier, 0.8)); + EXPECT_TRUE(wo_sp.setPointer(SurfaceProperty_IncidentSolarMultiplierFields::IncidentSolarMultiplierScheduleName, multSch.handle())); + + Model m = rt.translateWorkspace(w); + + EXPECT_EQ(1, m.getConcreteModelObjects().size()); + EXPECT_EQ(1, m.getConcreteModelObjects().size()); + + auto sps = m.getConcreteModelObjects(); + ASSERT_EQ(1, sps.size()); + auto& sp = sps[0]; + EXPECT_EQ("SubSurface 1", sp.subSurface().nameString()); + EXPECT_EQ(0.8, sp.incidentSolarMultiplier()); + ASSERT_TRUE(sp.incidentSolarMultiplierSchedule()); + EXPECT_EQ("multSch", sp.incidentSolarMultiplierSchedule()->nameString()); +} diff --git a/src/energyplus/Test/SurfacePropertyLocalEnvironment_GTest.cpp b/src/energyplus/Test/SurfacePropertyLocalEnvironment_GTest.cpp index 1a6ac0f6bb..fe6ee18ce4 100644 --- a/src/energyplus/Test/SurfacePropertyLocalEnvironment_GTest.cpp +++ b/src/energyplus/Test/SurfacePropertyLocalEnvironment_GTest.cpp @@ -122,6 +122,9 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_SurfacePropertyLocalEnvironment) { // Assigned to a Surface Workspace w = ft.translateModel(m); + ASSERT_EQ(1, w.getObjectsByType(IddObjectType::BuildingSurface_Detailed).size()); + ASSERT_EQ(1, w.getObjectsByType(IddObjectType::FenestrationSurface_Detailed).size()); + std::vector idfObjs = w.getObjectsByType(IddObjectType::SurfaceProperty_LocalEnvironment); ASSERT_EQ(1, idfObjs.size()); auto& wo_localEnv = idfObjs[0]; @@ -148,6 +151,9 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_SurfacePropertyLocalEnvironment) { // Assigned to a SubSurface Workspace w = ft.translateModel(m); + ASSERT_EQ(1, w.getObjectsByType(IddObjectType::BuildingSurface_Detailed).size()); + ASSERT_EQ(1, w.getObjectsByType(IddObjectType::FenestrationSurface_Detailed).size()); + std::vector idfObjs = w.getObjectsByType(IddObjectType::SurfaceProperty_LocalEnvironment); ASSERT_EQ(1, idfObjs.size()); auto& wo_localEnv = idfObjs[0]; diff --git a/src/model/CMakeLists.txt b/src/model/CMakeLists.txt index b57ee8784c..30e15e8c4b 100644 --- a/src/model/CMakeLists.txt +++ b/src/model/CMakeLists.txt @@ -1543,6 +1543,12 @@ set(${target_name}_src SurfacePropertySurroundingSurfaces.cpp SurfacePropertySurroundingSurfaces.hpp SurfacePropertySurroundingSurfaces_Impl.hpp + SurfacePropertyGroundSurfaces.cpp + SurfacePropertyGroundSurfaces.hpp + SurfacePropertyGroundSurfaces_Impl.hpp + SurfacePropertyIncidentSolarMultiplier.cpp + SurfacePropertyIncidentSolarMultiplier.hpp + SurfacePropertyIncidentSolarMultiplier_Impl.hpp SwimmingPoolIndoor.cpp SwimmingPoolIndoor.hpp SwimmingPoolIndoor_Impl.hpp @@ -2242,6 +2248,8 @@ set(${target_name}_test_src test/SurfacePropertyOtherSideCoefficients_GTest.cpp test/SurfacePropertyExposedFoundationPerimeter_GTest.cpp test/SurfacePropertySurroundingSurfaces_GTest.cpp + test/SurfacePropertyGroundSurfaces_GTest.cpp + test/SurfacePropertyIncidentSolarMultiplier_GTest.cpp test/SwimmingPoolIndoor_GTest.cpp test/TableMultiVariableLookup_GTest.cpp test/TableLookup_GTest.cpp diff --git a/src/model/ConcreteModelObjects.hpp b/src/model/ConcreteModelObjects.hpp index d0af21b767..b3e0264348 100644 --- a/src/model/ConcreteModelObjects.hpp +++ b/src/model/ConcreteModelObjects.hpp @@ -490,6 +490,8 @@ #include "SurfacePropertyOtherSideCoefficients.hpp" #include "SurfacePropertyOtherSideConditionsModel.hpp" #include "SurfacePropertySurroundingSurfaces.hpp" +#include "SurfacePropertyGroundSurfaces.hpp" +#include "SurfacePropertyIncidentSolarMultiplier.hpp" #include "SwimmingPoolIndoor.hpp" #include "TableMultiVariableLookup.hpp" #include "TableLookup.hpp" @@ -1022,6 +1024,8 @@ #include "SurfacePropertyOtherSideCoefficients_Impl.hpp" #include "SurfacePropertyOtherSideConditionsModel_Impl.hpp" #include "SurfacePropertySurroundingSurfaces_Impl.hpp" +#include "SurfacePropertyGroundSurfaces_Impl.hpp" +#include "SurfacePropertyIncidentSolarMultiplier_Impl.hpp" #include "SwimmingPoolIndoor_Impl.hpp" #include "TableMultiVariableLookup_Impl.hpp" #include "TableLookup_Impl.hpp" diff --git a/src/model/Model.cpp b/src/model/Model.cpp index 7c45328458..db96379c9c 100644 --- a/src/model/Model.cpp +++ b/src/model/Model.cpp @@ -4257,6 +4257,8 @@ namespace model { REGISTER_CONSTRUCTOR(SurfacePropertyOtherSideCoefficients); REGISTER_CONSTRUCTOR(SurfacePropertyOtherSideConditionsModel); REGISTER_CONSTRUCTOR(SurfacePropertySurroundingSurfaces); + REGISTER_CONSTRUCTOR(SurfacePropertyGroundSurfaces); + REGISTER_CONSTRUCTOR(SurfacePropertyIncidentSolarMultiplier); REGISTER_CONSTRUCTOR(SwimmingPoolIndoor); #if defined(_MSC_VER) # pragma warning(push) @@ -4809,6 +4811,8 @@ namespace model { REGISTER_COPYCONSTRUCTORS(SurfacePropertyOtherSideCoefficients); REGISTER_COPYCONSTRUCTORS(SurfacePropertyOtherSideConditionsModel); REGISTER_COPYCONSTRUCTORS(SurfacePropertySurroundingSurfaces); + REGISTER_COPYCONSTRUCTORS(SurfacePropertyGroundSurfaces); + REGISTER_COPYCONSTRUCTORS(SurfacePropertyIncidentSolarMultiplier); REGISTER_COPYCONSTRUCTORS(SwimmingPoolIndoor); #if defined(_MSC_VER) # pragma warning(push) diff --git a/src/model/ModelGeometry.i b/src/model/ModelGeometry.i index 3ae7600afb..b2113b882d 100644 --- a/src/model/ModelGeometry.i +++ b/src/model/ModelGeometry.i @@ -174,6 +174,15 @@ class ExteriorLoadInstance; } }; +%extend openstudio::model::GroundSurfaceGroup { + // Use the overloaded operator<< for string representation + std::string __str__() { + std::ostringstream os; + os << *$self; + return os.str(); + } +}; + UNIQUEMODELOBJECT_TEMPLATES(Site); UNIQUEMODELOBJECT_TEMPLATES(Facility); UNIQUEMODELOBJECT_TEMPLATES(Building); @@ -200,6 +209,9 @@ MODELOBJECT_TEMPLATES(SurfacePropertyOtherSideConditionsModel); MODELOBJECT_TEMPLATES(SurfacePropertyLocalEnvironment); MODELOBJECT_TEMPLATES(SurroundingSurfaceGroup); // helper for extensible fields for SurfacePropertySurroundingSurfaces MODELOBJECT_TEMPLATES(SurfacePropertySurroundingSurfaces); +MODELOBJECT_TEMPLATES(GroundSurfaceGroup); // helper for extensible fields for SurfacePropertyGroundSurfaces +MODELOBJECT_TEMPLATES(SurfacePropertyGroundSurfaces); +MODELOBJECT_TEMPLATES(SurfacePropertyIncidentSolarMultiplier); MODELOBJECT_TEMPLATES(SurfacePropertyConvectionCoefficients); MODELOBJECT_TEMPLATES(People); MODELOBJECT_TEMPLATES(Luminaire); @@ -256,6 +268,8 @@ SWIG_MODELOBJECT(SurfacePropertyOtherSideCoefficients, 1); SWIG_MODELOBJECT(SurfacePropertyOtherSideConditionsModel, 1); SWIG_MODELOBJECT(SurfacePropertyLocalEnvironment, 1); SWIG_MODELOBJECT(SurfacePropertySurroundingSurfaces, 1); +SWIG_MODELOBJECT(SurfacePropertyGroundSurfaces, 1); +SWIG_MODELOBJECT(SurfacePropertyIncidentSolarMultiplier, 1); SWIG_MODELOBJECT(SurfacePropertyConvectionCoefficients, 1); SWIG_MODELOBJECT(People, 1); SWIG_MODELOBJECT(Luminaire, 1); diff --git a/src/model/ScheduleTypeRegistry.cpp b/src/model/ScheduleTypeRegistry.cpp index 1859c0843d..c53bd048a0 100644 --- a/src/model/ScheduleTypeRegistry.cpp +++ b/src/model/ScheduleTypeRegistry.cpp @@ -399,6 +399,12 @@ namespace model { {"SurfacePropertySurroundingSurfaces", "Sky Temperature", "skyTemperatureSchedule", true, "Temperature", OptionalDouble(), OptionalDouble()}, {"SurfacePropertySurroundingSurfaces", "Ground Temperature", "groundTemperatureSchedule", true, "Temperature", OptionalDouble(), OptionalDouble()}, + {"SurfacePropertySurroundingSurfaces", "Surrounding Surface Temperature Schedule", "surroundingSurfaceTemperatureSchedule", true, "Temperature", + OptionalDouble(), OptionalDouble()}, + {"SurfacePropertyGroundSurfaces", "Ground Surface Temperature", "groundSurfaceTemperatureSchedule", true, "Temperature", OptionalDouble(), + OptionalDouble()}, + {"SurfacePropertyGroundSurfaces", "Ground Surface Reflectance", "groundSurfaceReflectanceSchedule", true, "", 0.0, 1.0}, + {"SurfacePropertyIncidentSolarMultiplier", "Incident Solar Multiplier", "incidentSolarMultiplierSchedule", true, "", 0.0, 1.0}, {"SurfacePropertyLocalEnvironment", "External Shading Fraction", "externalShadingFractionSchedule", true, "", 0.0, 1.0}, {"SwimmingPoolIndoor", "Activity Factor", "activityFactorSchedule", true, "", 0.0, OptionalDouble()}, // can exceed 1.0, for wave pools for eg {"SwimmingPoolIndoor", "Make-up Water Supply", "makeupWaterSupplySchedule", true, "Temperature", OptionalDouble(), OptionalDouble()}, diff --git a/src/model/SubSurface.cpp b/src/model/SubSurface.cpp index 145ac6dcae..14217338e9 100644 --- a/src/model/SubSurface.cpp +++ b/src/model/SubSurface.cpp @@ -62,6 +62,8 @@ #include "SurfacePropertyConvectionCoefficients_Impl.hpp" #include "SurfacePropertyLocalEnvironment.hpp" #include "SurfacePropertyLocalEnvironment_Impl.hpp" +#include "SurfacePropertyIncidentSolarMultiplier.hpp" +#include "SurfacePropertyIncidentSolarMultiplier_Impl.hpp" #include "AirflowNetworkSurface.hpp" #include "AirflowNetworkSurface_Impl.hpp" #include "AirflowNetworkDetailedOpening.hpp" @@ -916,6 +918,24 @@ namespace model { } } + boost::optional SubSurface_Impl::surfacePropertyIncidentSolarMultiplier() const { + std::vector allspism(model().getConcreteModelObjects()); + std::vector spism; + for (auto& spcc : allspism) { + if (spcc.subSurface().handle() == handle()) { + spism.push_back(spcc); + } + } + if (spism.empty()) { + return boost::none; + } else if (spism.size() == 1) { + return spism.at(0); + } else { + LOG(Error, "More than one SurfacePropertyIncidentSolarMultiplier points to this SubSurface"); + return boost::none; + } + } + boost::optional SubSurface_Impl::surfacePropertyOtherSideCoefficients() const { return getObject().getModelObjectTarget(OS_SubSurfaceFields::OutsideBoundaryConditionObject); } @@ -1564,6 +1584,10 @@ namespace model { return getImpl()->surfacePropertyLocalEnvironment(); } + boost::optional SubSurface::surfacePropertyIncidentSolarMultiplier() const { + return getImpl()->surfacePropertyIncidentSolarMultiplier(); + } + boost::optional SubSurface::surfacePropertyOtherSideCoefficients() const { return getImpl()->surfacePropertyOtherSideCoefficients(); } diff --git a/src/model/SubSurface.hpp b/src/model/SubSurface.hpp index 26413e134a..a7aaa4ec57 100644 --- a/src/model/SubSurface.hpp +++ b/src/model/SubSurface.hpp @@ -49,6 +49,7 @@ namespace model { class SurfacePropertyOtherSideConditionsModel; class SurfacePropertyConvectionCoefficients; class SurfacePropertyLocalEnvironment; + class SurfacePropertyIncidentSolarMultiplier; class AirflowNetworkSurface; class AirflowNetworkDetailedOpening; class AirflowNetworkSimpleOpening; @@ -199,6 +200,9 @@ namespace model { /** Returns the SurfacePropertyLocalEnvironment, if it exists. */ boost::optional surfacePropertyLocalEnvironment() const; + /** Return the SurfacePropertyIncidentSolarMultiplier that points to this surface if any */ + boost::optional surfacePropertyIncidentSolarMultiplier() const; + /** Returns the adjacent SurfaceSurfacePropertyOtherSideCoefficients, if it exists. */ boost::optional surfacePropertyOtherSideCoefficients() const; diff --git a/src/model/SubSurface_Impl.hpp b/src/model/SubSurface_Impl.hpp index c2caa31030..50eb8ba012 100644 --- a/src/model/SubSurface_Impl.hpp +++ b/src/model/SubSurface_Impl.hpp @@ -51,6 +51,7 @@ namespace model { class SurfacePropertyOtherSideConditionsModel; class SurfacePropertyConvectionCoefficients; class SurfacePropertyLocalEnvironment; + class SurfacePropertyIncidentSolarMultiplier; namespace detail { @@ -237,6 +238,8 @@ namespace model { boost::optional surfacePropertyLocalEnvironment() const; + boost::optional surfacePropertyIncidentSolarMultiplier() const; + /** Returns the adjacent SurfaceSurfacePropertyOtherSideCoefficients, if it exists. */ boost::optional surfacePropertyOtherSideCoefficients() const; diff --git a/src/model/SurfacePropertyGroundSurfaces.cpp b/src/model/SurfacePropertyGroundSurfaces.cpp new file mode 100644 index 0000000000..1c4a5bfa7a --- /dev/null +++ b/src/model/SurfacePropertyGroundSurfaces.cpp @@ -0,0 +1,423 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +* following conditions are met: +* +* (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following +* disclaimer. +* +* (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided with the distribution. +* +* (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products +* derived from this software without specific prior written permission from the respective party. +* +* (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works +* may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior +* written permission from Alliance for Sustainable Energy, LLC. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED +* STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +***********************************************************************************************************************/ + +#include "SurfacePropertyGroundSurfaces.hpp" +#include "SurfacePropertyGroundSurfaces_Impl.hpp" + +#include "Schedule.hpp" +#include "Schedule_Impl.hpp" +#include "ScheduleTypeLimits.hpp" +#include "ScheduleTypeRegistry.hpp" +#include "ModelExtensibleGroup.hpp" +#include "SurfacePropertyLocalEnvironment.hpp" +#include "SurfacePropertyLocalEnvironment_Impl.hpp" + +#include +#include +#include + +#include "../utilities/core/Assert.hpp" + +namespace openstudio { +namespace model { + + /*************************************************************************************************************************************************** + * G R O U N D S U R F A C E G R O U P W R A P P E R * + **************************************************************************************************************************************************/ + + GroundSurfaceGroup::GroundSurfaceGroup(std::string groundSurfaceName, double viewFactor, boost::optional temperatureSchedule, + boost::optional reflectanceSchedule) + : m_groundSurfaceName(std::move(groundSurfaceName)), + m_viewFactor(viewFactor), + m_temperatureSch(std::move(temperatureSchedule)), + m_reflectanceSch(std::move(reflectanceSchedule)) { + + // Matches the maximum value in IDD + if (m_viewFactor > 1) { + LOG_AND_THROW("Unable to create GroundSurfaceGroup, View Factor of " << m_viewFactor << " cannot be more than 1."); + } else if (m_viewFactor < 0) { + LOG_AND_THROW("Unable to create GroundSurfaceGroup, View Factor of " << m_viewFactor << " cannot be less than 0."); + } + + if (m_groundSurfaceName.empty()) { + LOG_AND_THROW("Unable to create GroundSurfaceGroup, GroundSurfaceName cannot be empty."); + } + } + + std::string GroundSurfaceGroup::groundSurfaceName() const { + return m_groundSurfaceName; + } + + double GroundSurfaceGroup::viewFactor() const { + return m_viewFactor; + } + + boost::optional GroundSurfaceGroup::temperatureSchedule() const { + return m_temperatureSch; + } + + boost::optional GroundSurfaceGroup::reflectanceSchedule() const { + return m_reflectanceSch; + } + + std::ostream& operator<<(std::ostream& out, const openstudio::model::GroundSurfaceGroup& groundSurfaceGroup) { + out << "(Surface = '" << groundSurfaceGroup.groundSurfaceName() << "', " + << "View Factor = " << groundSurfaceGroup.viewFactor() << ", "; + if (groundSurfaceGroup.temperatureSchedule()) { + out << "Temperature Schedule = '" << groundSurfaceGroup.temperatureSchedule()->nameString() << "', "; + } else { + out << "No Temperature Schedule Assigned, "; + } + if (groundSurfaceGroup.reflectanceSchedule()) { + out << "Reflectance Schedule = '" << groundSurfaceGroup.reflectanceSchedule()->nameString() << "')"; + } else { + out << "No Reflectance Schedule Assigned)"; + } + return out; + } + + namespace detail { + + SurfacePropertyGroundSurfaces_Impl::SurfacePropertyGroundSurfaces_Impl(const IdfObject& idfObject, Model_Impl* model, bool keepHandle) + : ModelObject_Impl(idfObject, model, keepHandle) { + OS_ASSERT(idfObject.iddObject().type() == SurfacePropertyGroundSurfaces::iddObjectType()); + } + + SurfacePropertyGroundSurfaces_Impl::SurfacePropertyGroundSurfaces_Impl(const openstudio::detail::WorkspaceObject_Impl& other, Model_Impl* model, + bool keepHandle) + : ModelObject_Impl(other, model, keepHandle) { + OS_ASSERT(other.iddObject().type() == SurfacePropertyGroundSurfaces::iddObjectType()); + } + + SurfacePropertyGroundSurfaces_Impl::SurfacePropertyGroundSurfaces_Impl(const SurfacePropertyGroundSurfaces_Impl& other, Model_Impl* model, + bool keepHandle) + : ModelObject_Impl(other, model, keepHandle) {} + + const std::vector& SurfacePropertyGroundSurfaces_Impl::outputVariableNames() const { + static std::vector result; + if (result.empty()) { + } + return result; + } + + IddObjectType SurfacePropertyGroundSurfaces_Impl::iddObjectType() const { + return SurfacePropertyGroundSurfaces::iddObjectType(); + } + + std::vector SurfacePropertyGroundSurfaces_Impl::getScheduleTypeKeys(const Schedule& schedule) const { + std::vector result; + + // This is unusual, but the schedule is in the Extensible Fields (and only there) + // UnsignedVector fieldIndices = getSourceIndices(schedule.handle()); + UnsignedVector fieldIndices; + for (const ModelExtensibleGroup& group : castVector(extensibleGroups())) { + UnsignedVector thisFieldIndices = group.getSourceFieldIndices(schedule.handle()); + fieldIndices.insert(fieldIndices.end(), thisFieldIndices.begin(), thisFieldIndices.end()); + } + + // Make unique, have to sort before calling unique, unique only works on consecutive elements + std::sort(fieldIndices.begin(), fieldIndices.end()); + fieldIndices.erase(std::unique(fieldIndices.begin(), fieldIndices.end()), fieldIndices.end()); + + UnsignedVector::const_iterator b(fieldIndices.begin()); + UnsignedVector::const_iterator e(fieldIndices.end()); + if (std::find(b, e, OS_SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceTemperatureScheduleName) != e) { + result.emplace_back("SurfacePropertyGroundSurfaces", "Ground Surface Temperature"); + } else if (std::find(b, e, OS_SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceReflectanceScheduleName) != e) { + result.emplace_back("SurfacePropertyGroundSurfaces", "Ground Surface Reflectance"); + } + + return result; + } + + // Extensible groups + + unsigned int SurfacePropertyGroundSurfaces_Impl::numberofGroundSurfaceGroups() const { + return numExtensibleGroups(); + } + + boost::optional SurfacePropertyGroundSurfaces_Impl::groundSurfaceGroupIndex(const std::string& groundSurfaceName) const { + boost::optional result; + + // Find with custom predicate, checking handle equality between the toSurface and the fromSurface pairs + // We do it with extensibleGroups() (rather than groundSurfaceGroups()) and getString to avoid overhead + // of manipulating actual model objects (getTarget, then create a GroundSurfaceGroups wrapper, get handle convert to string...) + // and speed up the routine + auto egs = castVector(extensibleGroups()); + auto it = std::find_if(egs.begin(), egs.end(), [&groundSurfaceName](const WorkspaceExtensibleGroup& eg) { + return openstudio::istringEqual(eg.getField(OS_SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceName).get(), groundSurfaceName); + }); + + // If found, we compute the index by using std::distance between the start of vector and the iterator returned by std::find_if + if (it != egs.end()) { + result = std::distance(egs.begin(), it); + } + + return result; + } + + boost::optional SurfacePropertyGroundSurfaces_Impl::groundSurfaceGroupIndex(const GroundSurfaceGroup& groundSurfaceGroup) const { + return groundSurfaceGroupIndex(groundSurfaceGroup.groundSurfaceName()); + } + + boost::optional SurfacePropertyGroundSurfaces_Impl::getGroundSurfaceGroup(unsigned groupIndex) const { + + boost::optional result; + + if (groupIndex >= numberofGroundSurfaceGroups()) { + LOG(Error, "Asked to get GroundSurfaceGroup with index " << groupIndex << ", but " << briefDescription() << " has just " + << numberofGroundSurfaceGroups() << " GroundSurfaceGroups."); + return result; + } + + auto group = getExtensibleGroup(groupIndex).cast(); + + boost::optional surfaceName_ = group.getString(OS_SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceName); + boost::optional viewFactor_ = group.getDouble(OS_SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceViewFactor); + boost::optional tempSch_ = + group.getModelObjectTarget(OS_SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceTemperatureScheduleName); + + boost::optional reflectanceSch_ = + group.getModelObjectTarget(OS_SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceReflectanceScheduleName); + + if (!surfaceName_) { + LOG(Error, "Could not retrieve GroundSurfaceName for extensible group " << group.groupIndex() << "."); + } + if (!viewFactor_) { + LOG(Error, "Could not retrieve GroundSurfaceViewFactor for extensible group " << group.groupIndex() << "."); + } + + // Schedules are optional + + result = GroundSurfaceGroup(surfaceName_.get(), viewFactor_.get(), tempSch_, reflectanceSch_); + + return result; + } + + bool SurfacePropertyGroundSurfaces_Impl::addGroundSurfaceGroup(const GroundSurfaceGroup& groundSurfaceGroup) { + + // Bounds checking happens in the GroundSurfaceGroup ctor + + // Check if viewFactor already exists + boost::optional _existingIndex = groundSurfaceGroupIndex(groundSurfaceGroup); + if (_existingIndex) { + boost::optional _group = getGroundSurfaceGroup(_existingIndex.get()); + OS_ASSERT(_group); + LOG(Warn, "For " << briefDescription() << ", GroundSurfaceGroup already exists, will be modified in place from " << _group.get() << " to " + << groundSurfaceGroup << "."); + } + + // If existing, get it, otherwise Push an extensible group. ModelExtensibleGroup cannot be default-constructed, so use a ternary operator + // Given that we will potentially push many extensible groups + // we will suffer from going through the internal checks in WorkspaceObject, especially in setPointer, + // and performance will be roughly O(n^2) when adding groups. + // So to improve the performance we pushExtensible group without validity check, and call setPointer without validity check (`isValid`) + std::vector temp; + ModelExtensibleGroup eg = (_existingIndex ? getExtensibleGroup(_existingIndex.get()).cast() + : pushExtensibleGroup(temp, false).cast()); + + bool result = false; + + bool surfaceNameOk = eg.setString(OS_SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceName, groundSurfaceGroup.groundSurfaceName()); + + bool viewFactorOk = eg.setDouble(OS_SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceViewFactor, groundSurfaceGroup.viewFactor()); + + bool schTempOk = true; + if (auto sch_ = groundSurfaceGroup.temperatureSchedule()) { + schTempOk = eg.setPointer(OS_SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceTemperatureScheduleName, sch_->handle(), false); + if (!schTempOk) { + LOG(Error, "Unable to add Ground Surface Group which has an incompatible Temperature Schedule to " << briefDescription()); + OS_ASSERT(false); + } + } else { + eg.setString(OS_SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceTemperatureScheduleName, ""); + } + + bool schRefOk = true; + if (auto sch_ = groundSurfaceGroup.reflectanceSchedule()) { + schRefOk = eg.setPointer(OS_SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceReflectanceScheduleName, sch_->handle(), false); + if (!schRefOk) { + LOG(Error, "Unable to add Ground Surface Group which has an incompatible Reflectance Schedule to " << briefDescription()); + + OS_ASSERT(false); + } + } else { + eg.setString(OS_SurfaceProperty_GroundSurfacesExtensibleFields::GroundSurfaceReflectanceScheduleName, ""); + } + + if (surfaceNameOk && viewFactorOk && schTempOk && schRefOk) { + result = true; + } else { + // Something went wrong + // So erase the new extensible group + getObject().eraseExtensibleGroup(eg.groupIndex()); + result = false; + } + return result; + } + + // Overloads, it creates a GroundSurfaceGroup wrapper, then call `addGroundSurfaceGroup(const GroundSurfaceGroup& groundSurfaceGroup)` + bool SurfacePropertyGroundSurfaces_Impl::addGroundSurfaceGroup(const std::string& groundSurfaceName, double viewFactor, + boost::optional temperatureSchedule, + boost::optional reflectanceSchedule) { + GroundSurfaceGroup groundSurfaceGroup(groundSurfaceName, viewFactor, std::move(temperatureSchedule), std::move(reflectanceSchedule)); + return addGroundSurfaceGroup(groundSurfaceGroup); + } + + bool SurfacePropertyGroundSurfaces_Impl::addGroundSurfaceGroups(const std::vector& groundSurfaceGroups) { + bool result = true; + + for (const auto& groundSurfaceGroup : groundSurfaceGroups) { + bool thisResult = addGroundSurfaceGroup(groundSurfaceGroup); + if (!thisResult) { + LOG(Error, "Could not add groundSurfaceGroup " << groundSurfaceGroup << " to " << briefDescription() << ". Continuing with others."); + // OS_ASSERT(false); + // result = false; + } + } + + return result; + } + + bool SurfacePropertyGroundSurfaces_Impl::removeGroundSurfaceGroup(unsigned groupIndex) { + bool result = false; + + unsigned int num = numberofGroundSurfaceGroups(); + if (groupIndex < num) { + getObject().eraseExtensibleGroup(groupIndex); + result = true; + } + return result; + } + + void SurfacePropertyGroundSurfaces_Impl::removeAllGroundSurfaceGroups() { + getObject().clearExtensibleGroups(); + } + + std::vector SurfacePropertyGroundSurfaces_Impl::groundSurfaceGroups() const { + std::vector result; + + for (unsigned i = 0; i < numberofGroundSurfaceGroups(); ++i) { + + boost::optional group_ = getGroundSurfaceGroup(i); + + // getViewFactor is responsible for handling error and issuing Error log messages. + // Here we add it to the result array if it worked, and if it didn't, we keep going + // We just issue a message about index so user can delete it easily + if (group_) { + result.push_back(group_.get()); + } else { + LOG(Error, briefDescription() << " has an invalid GroundSurfaceGroup group at index " << i); + } + } + + return result; + } + + // Helper + boost::optional SurfacePropertyGroundSurfaces_Impl::surfacePropertyLocalEnvironment() const { + std::vector localEnvs = + getObject().getModelObjectSources(SurfacePropertyLocalEnvironment::iddObjectType()); + if (localEnvs.empty()) { + return boost::none; + } else if (localEnvs.size() == 1) { + return localEnvs.at(0); + } else { + LOG(Error, "More than one SurfacePropertyLocalEnvironments point to this SurfacePropertyGroundSurfaces"); + return boost::none; + } + } + + } // namespace detail + + SurfacePropertyGroundSurfaces::SurfacePropertyGroundSurfaces(const Model& model) + : ModelObject(SurfacePropertyGroundSurfaces::iddObjectType(), model) { + OS_ASSERT(getImpl()); + } + + IddObjectType SurfacePropertyGroundSurfaces::iddObjectType() { + return {IddObjectType::OS_SurfaceProperty_GroundSurfaces}; + } + + // Extensible fields + + std::vector SurfacePropertyGroundSurfaces::groundSurfaceGroups() const { + return getImpl()->groundSurfaceGroups(); + } + + unsigned int SurfacePropertyGroundSurfaces::numberofGroundSurfaceGroups() const { + return getImpl()->numberofGroundSurfaceGroups(); + } + + boost::optional SurfacePropertyGroundSurfaces::groundSurfaceGroupIndex(const GroundSurfaceGroup& groundSurfaceGroup) const { + return getImpl()->groundSurfaceGroupIndex(groundSurfaceGroup); + } + boost::optional SurfacePropertyGroundSurfaces::groundSurfaceGroupIndex(const std::string& groundSurfaceName) const { + return getImpl()->groundSurfaceGroupIndex(groundSurfaceName); + } + + boost::optional SurfacePropertyGroundSurfaces::getGroundSurfaceGroup(unsigned groupIndex) const { + return getImpl()->getGroundSurfaceGroup(groupIndex); + } + + bool SurfacePropertyGroundSurfaces::addGroundSurfaceGroup(const GroundSurfaceGroup& groundSurfaceGroup) { + return getImpl()->addGroundSurfaceGroup(groundSurfaceGroup); + } + + // Overloads, it creates a GroundSurfaceGroup wrapper, then call `addGroundSurfaceGroup(const GroundSurfaceGroup& groundSurfaceGroup)` + bool SurfacePropertyGroundSurfaces::addGroundSurfaceGroup(const std::string& groundSurfaceName, double viewFactor, + boost::optional temperatureSchedule, + boost::optional reflectanceSchedule) { + return getImpl()->addGroundSurfaceGroup(groundSurfaceName, viewFactor, std::move(temperatureSchedule), + std::move(reflectanceSchedule)); + } + + bool SurfacePropertyGroundSurfaces::addGroundSurfaceGroups(const std::vector& groundSurfaceGroups) { + return getImpl()->addGroundSurfaceGroups(groundSurfaceGroups); + } + + bool SurfacePropertyGroundSurfaces::removeGroundSurfaceGroup(unsigned groupIndex) { + return getImpl()->removeGroundSurfaceGroup(groupIndex); + } + + void SurfacePropertyGroundSurfaces::removeAllGroundSurfaceGroups() { + getImpl()->removeAllGroundSurfaceGroups(); + } + + boost::optional SurfacePropertyGroundSurfaces::surfacePropertyLocalEnvironment() const { + return getImpl()->surfacePropertyLocalEnvironment(); + } + + /// @cond + SurfacePropertyGroundSurfaces::SurfacePropertyGroundSurfaces(std::shared_ptr impl) + : ModelObject(std::move(impl)) {} + /// @endcond + +} // namespace model +} // namespace openstudio diff --git a/src/model/SurfacePropertyGroundSurfaces.hpp b/src/model/SurfacePropertyGroundSurfaces.hpp new file mode 100644 index 0000000000..c9becafe8f --- /dev/null +++ b/src/model/SurfacePropertyGroundSurfaces.hpp @@ -0,0 +1,151 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +* following conditions are met: +* +* (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following +* disclaimer. +* +* (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided with the distribution. +* +* (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products +* derived from this software without specific prior written permission from the respective party. +* +* (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works +* may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior +* written permission from Alliance for Sustainable Energy, LLC. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED +* STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +***********************************************************************************************************************/ + +#ifndef MODEL_SURFACEPROPERTYGROUNDSURFACES_HPP +#define MODEL_SURFACEPROPERTYGROUNDSURFACES_HPP + +#include +#include "ModelObject.hpp" +#include "Schedule.hpp" + +namespace openstudio { +namespace model { + + class SurfacePropertyLocalEnvironment; + + namespace detail { + + class SurfacePropertyGroundSurfaces_Impl; + + } // namespace detail + + /** This class implements an extensible group */ + class MODEL_API GroundSurfaceGroup + { + public: + GroundSurfaceGroup(std::string groundSurfaceName, double viewFactor, boost::optional temperatureSchedule = boost::none, + boost::optional reflectanceSchedule = boost::none); + + std::string groundSurfaceName() const; + double viewFactor() const; + boost::optional temperatureSchedule() const; + + boost::optional reflectanceSchedule() const; + + private: + // From + std::string m_groundSurfaceName; + double m_viewFactor; + boost::optional m_temperatureSch; + boost::optional m_reflectanceSch; + REGISTER_LOGGER("openstudio.model.GroundSurfaceGroup"); + }; + + // Overload operator<< + MODEL_API std::ostream& operator<<(std::ostream& out, const openstudio::model::GroundSurfaceGroup& groundSurfaceGroup); + + /** SurfacePropertyGroundSurfaces is a ModelObject that wraps the OpenStudio IDD object 'OS:SurfaceProperty:GroundSurfaces'. */ + class MODEL_API SurfacePropertyGroundSurfaces : public ModelObject + { + public: + /** @name Constructors and Destructors */ + //@{ + + explicit SurfacePropertyGroundSurfaces(const Model& model); + + virtual ~SurfacePropertyGroundSurfaces() = default; + + //@} + + static IddObjectType iddObjectType(); + + /** @name Getters */ + //@{ + + //@} + /** @name Setters */ + //@{ + + //@} + /** @name Other */ + //@{ + + // Helper to get the parent SurfaceProperty:LocalEnvironment object + boost::optional surfacePropertyLocalEnvironment() const; + + // Handle this object's extensible fields. + std::vector groundSurfaceGroups() const; + + unsigned int numberofGroundSurfaceGroups() const; + + /** Looks up by Surface Name (case-insensitive) */ + boost::optional groundSurfaceGroupIndex(const GroundSurfaceGroup& groundSurfaceGroup) const; + boost::optional groundSurfaceGroupIndex(const std::string& groundSurfaceName) const; + + boost::optional getGroundSurfaceGroup(unsigned groupIndex) const; + + /** If a groundSurfaceGroup group is already present (cf `groundSurfaceGroupIndex()`), it will Warn and override the groundSurfaceGroup value */ + bool addGroundSurfaceGroup(const GroundSurfaceGroup& groundSurfaceGroup); + + // Overloads, it creates a GroundSurfaceGroup wrapper, then call `addGroundSurfaceGroup(const GroundSurfaceGroup& groundSurfaceGroup)` + bool addGroundSurfaceGroup(const std::string& groundSurfaceName, double viewFactor, boost::optional temperatureSchedule = boost::none, + boost::optional reflectanceSchedule = boost::none); + + bool addGroundSurfaceGroups(const std::vector& groundSurfaceGroups); + + bool removeGroundSurfaceGroup(unsigned groupIndex); + + void removeAllGroundSurfaceGroups(); + + //@} + protected: + /// @cond + using ImplType = detail::SurfacePropertyGroundSurfaces_Impl; + + explicit SurfacePropertyGroundSurfaces(std::shared_ptr impl); + + friend class detail::SurfacePropertyGroundSurfaces_Impl; + friend class Model; + friend class IdfObject; + friend class openstudio::detail::IdfObject_Impl; + /// @endcond + private: + REGISTER_LOGGER("openstudio.model.SurfacePropertyGroundSurfaces"); + }; + + /** \relates SurfacePropertyGroundSurfaces*/ + using OptionalSurfacePropertyGroundSurfaces = boost::optional; + + /** \relates SurfacePropertyGroundSurfaces*/ + using SurfacePropertyGroundSurfacesVector = std::vector; + +} // namespace model +} // namespace openstudio + +#endif // MODEL_SURFACEPROPERTYGROUNDSURFACES_HPP diff --git a/src/model/SurfacePropertyGroundSurfaces_Impl.hpp b/src/model/SurfacePropertyGroundSurfaces_Impl.hpp new file mode 100644 index 0000000000..e880379129 --- /dev/null +++ b/src/model/SurfacePropertyGroundSurfaces_Impl.hpp @@ -0,0 +1,118 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +* following conditions are met: +* +* (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following +* disclaimer. +* +* (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided with the distribution. +* +* (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products +* derived from this software without specific prior written permission from the respective party. +* +* (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works +* may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior +* written permission from Alliance for Sustainable Energy, LLC. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED +* STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +***********************************************************************************************************************/ + +#ifndef MODEL_SURFACEPROPERTYGROUNDSURFACES_IMPL_HPP +#define MODEL_SURFACEPROPERTYGROUNDSURFACES_IMPL_HPP + +#include +#include "ModelObject_Impl.hpp" +#include "Schedule.hpp" + +namespace openstudio { +namespace model { + + class GroundSurfaceGroup; + class SurfacePropertyLocalEnvironment; + + namespace detail { + + /** SurfacePropertyGroundSurfaces_Impl is a ModelObject_Impl that is the implementation class for SurfacePropertyGroundSurfaces.*/ + class MODEL_API SurfacePropertyGroundSurfaces_Impl : public ModelObject_Impl + { + public: + /** @name Constructors and Destructors */ + //@{ + + SurfacePropertyGroundSurfaces_Impl(const IdfObject& idfObject, Model_Impl* model, bool keepHandle); + + SurfacePropertyGroundSurfaces_Impl(const openstudio::detail::WorkspaceObject_Impl& other, Model_Impl* model, bool keepHandle); + + SurfacePropertyGroundSurfaces_Impl(const SurfacePropertyGroundSurfaces_Impl& other, Model_Impl* model, bool keepHandle); + + virtual ~SurfacePropertyGroundSurfaces_Impl() = default; + + //@} + /** @name Virtual Methods */ + //@{ + + virtual const std::vector& outputVariableNames() const override; + + virtual IddObjectType iddObjectType() const override; + + virtual std::vector getScheduleTypeKeys(const Schedule& schedule) const override; + + //@} + /** @name Getters */ + //@{ + + //@} + /** @name Setters */ + //@{ + + //@} + /** @name Other */ + //@{ + + boost::optional surfacePropertyLocalEnvironment() const; + + std::vector groundSurfaceGroups() const; + + unsigned int numberofGroundSurfaceGroups() const; + + /** Looks up by Surface Name (case-insensitive) */ + boost::optional groundSurfaceGroupIndex(const GroundSurfaceGroup& groundSurfaceGroup) const; + boost::optional groundSurfaceGroupIndex(const std::string& groundSurfaceName) const; + + boost::optional getGroundSurfaceGroup(unsigned groupIndex) const; + + /** If a groundSurfaceGroup group is already present (cf `groundSurfaceGroupIndex()`), it will Warn and override the groundSurfaceGroup value */ + bool addGroundSurfaceGroup(const GroundSurfaceGroup& groundSurfaceGroup); + + // Overloads, it creates a GroundSurfaceGroup wrapper, then call `addGroundSurfaceGroup(const GroundSurfaceGroup& groundSurfaceGroup)` + bool addGroundSurfaceGroup(const std::string& groundSurfaceName, double viewFactor, boost::optional temperatureSchedule = boost::none, + boost::optional reflectanceSchedule = boost::none); + + bool addGroundSurfaceGroups(const std::vector& groundSurfaceGroups); + + bool removeGroundSurfaceGroup(unsigned groupIndex); + + void removeAllGroundSurfaceGroups(); + + //@} + protected: + private: + REGISTER_LOGGER("openstudio.model.SurfacePropertyGroundSurfaces"); + }; + + } // namespace detail + +} // namespace model +} // namespace openstudio + +#endif // MODEL_SURFACEPROPERTYGROUNDSURFACES_IMPL_HPP diff --git a/src/model/SurfacePropertyIncidentSolarMultiplier.cpp b/src/model/SurfacePropertyIncidentSolarMultiplier.cpp new file mode 100644 index 0000000000..06ffe19fa4 --- /dev/null +++ b/src/model/SurfacePropertyIncidentSolarMultiplier.cpp @@ -0,0 +1,200 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +* following conditions are met: +* +* (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following +* disclaimer. +* +* (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided with the distribution. +* +* (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products +* derived from this software without specific prior written permission from the respective party. +* +* (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works +* may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior +* written permission from Alliance for Sustainable Energy, LLC. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED +* STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +***********************************************************************************************************************/ + +#include "SurfacePropertyIncidentSolarMultiplier.hpp" +#include "SurfacePropertyIncidentSolarMultiplier_Impl.hpp" + +#include "Model.hpp" +#include "SubSurface.hpp" +#include "SubSurface_Impl.hpp" +#include "Schedule.hpp" +#include "Schedule_Impl.hpp" +#include "ScheduleTypeLimits.hpp" +#include "ScheduleTypeRegistry.hpp" + +#include +#include + +#include "../utilities/units/Unit.hpp" + +#include "../utilities/core/Assert.hpp" + +namespace openstudio { +namespace model { + + namespace detail { + + SurfacePropertyIncidentSolarMultiplier_Impl::SurfacePropertyIncidentSolarMultiplier_Impl(const IdfObject& idfObject, Model_Impl* model, + bool keepHandle) + : ModelObject_Impl(idfObject, model, keepHandle) { + OS_ASSERT(idfObject.iddObject().type() == SurfacePropertyIncidentSolarMultiplier::iddObjectType()); + } + + SurfacePropertyIncidentSolarMultiplier_Impl::SurfacePropertyIncidentSolarMultiplier_Impl(const openstudio::detail::WorkspaceObject_Impl& other, + Model_Impl* model, bool keepHandle) + : ModelObject_Impl(other, model, keepHandle) { + OS_ASSERT(other.iddObject().type() == SurfacePropertyIncidentSolarMultiplier::iddObjectType()); + } + + SurfacePropertyIncidentSolarMultiplier_Impl::SurfacePropertyIncidentSolarMultiplier_Impl(const SurfacePropertyIncidentSolarMultiplier_Impl& other, + Model_Impl* model, bool keepHandle) + : ModelObject_Impl(other, model, keepHandle) {} + + const std::vector& SurfacePropertyIncidentSolarMultiplier_Impl::outputVariableNames() const { + static std::vector result; + if (result.empty()) { + } + return result; + } + + IddObjectType SurfacePropertyIncidentSolarMultiplier_Impl::iddObjectType() const { + return SurfacePropertyIncidentSolarMultiplier::iddObjectType(); + } + + std::vector SurfacePropertyIncidentSolarMultiplier_Impl::getScheduleTypeKeys(const Schedule& schedule) const { + std::vector result; + UnsignedVector fieldIndices = getSourceIndices(schedule.handle()); + UnsignedVector::const_iterator b(fieldIndices.begin()); + UnsignedVector::const_iterator e(fieldIndices.end()); + if (std::find(b, e, OS_SurfaceProperty_IncidentSolarMultiplierFields::IncidentSolarMultiplierScheduleName) != e) { + result.emplace_back("SurfacePropertyIncidentSolarMultiplier", "Incident Solar Multiplier"); + } + return result; + } + + SubSurface SurfacePropertyIncidentSolarMultiplier_Impl::subSurface() const { + boost::optional value = optionalSubSurface(); + if (!value) { + LOG_AND_THROW(briefDescription() << " does not have an Surface attached."); + } + return value.get(); + } + + double SurfacePropertyIncidentSolarMultiplier_Impl::incidentSolarMultiplier() const { + boost::optional value = getDouble(OS_SurfaceProperty_IncidentSolarMultiplierFields::IncidentSolarMultiplier, true); + OS_ASSERT(value); + return value.get(); + } + + boost::optional SurfacePropertyIncidentSolarMultiplier_Impl::incidentSolarMultiplierSchedule() const { + return getObject().getModelObjectTarget( + OS_SurfaceProperty_IncidentSolarMultiplierFields::IncidentSolarMultiplierScheduleName); + } + + bool SurfacePropertyIncidentSolarMultiplier_Impl::setSubSurface(const SubSurface& subSurface) { + bool result = setPointer(OS_SurfaceProperty_IncidentSolarMultiplierFields::SurfaceName, subSurface.handle()); + return result; + } + + bool SurfacePropertyIncidentSolarMultiplier_Impl::setIncidentSolarMultiplier(double incidentSolarMultiplier) { + bool result = setDouble(OS_SurfaceProperty_IncidentSolarMultiplierFields::IncidentSolarMultiplier, incidentSolarMultiplier); + return result; + } + + bool SurfacePropertyIncidentSolarMultiplier_Impl::setIncidentSolarMultiplierSchedule(Schedule& schedule) { + bool result = setSchedule(OS_SurfaceProperty_IncidentSolarMultiplierFields::IncidentSolarMultiplierScheduleName, + "SurfacePropertyIncidentSolarMultiplier", "Incident Solar Multiplier", schedule); + return result; + } + + void SurfacePropertyIncidentSolarMultiplier_Impl::resetIncidentSolarMultiplierSchedule() { + bool result = setString(OS_SurfaceProperty_IncidentSolarMultiplierFields::IncidentSolarMultiplierScheduleName, ""); + OS_ASSERT(result); + } + + boost::optional SurfacePropertyIncidentSolarMultiplier_Impl::optionalSubSurface() const { + return getObject().getModelObjectTarget(OS_SurfaceProperty_IncidentSolarMultiplierFields::SurfaceName); + } + + } // namespace detail + + SurfacePropertyIncidentSolarMultiplier::SurfacePropertyIncidentSolarMultiplier(const SubSurface& subSurface) + : ModelObject(SurfacePropertyIncidentSolarMultiplier::iddObjectType(), subSurface.model()) { + OS_ASSERT(getImpl()); + + auto subSurfaceType = subSurface.subSurfaceType(); + if (!(istringEqual("FixedWindow", subSurfaceType) || istringEqual("OperableWindow", subSurfaceType) + || istringEqual("Skylight", subSurfaceType))) { + LOG_AND_THROW("Wrong SubSurface Type: only accepts windows, was passed " << subSurface.briefDescription()); + } + bool ok = true; + ok = setSubSurface(subSurface); + OS_ASSERT(ok); + + // TODO: default to alwaysOnContinous? Or leave as optional? + // { + // auto schedule = subSurface.model().alwaysOnContinuousSchedule(); + // ok = setIncidentSolarMultiplierSchedule(schedule); + // OS_ASSERT(ok); + // } + + ok = setIncidentSolarMultiplier(1.0); + OS_ASSERT(ok); + } + + IddObjectType SurfacePropertyIncidentSolarMultiplier::iddObjectType() { + return {IddObjectType::OS_SurfaceProperty_IncidentSolarMultiplier}; + } + + SubSurface SurfacePropertyIncidentSolarMultiplier::subSurface() const { + return getImpl()->subSurface(); + } + + double SurfacePropertyIncidentSolarMultiplier::incidentSolarMultiplier() const { + return getImpl()->incidentSolarMultiplier(); + } + + boost::optional SurfacePropertyIncidentSolarMultiplier::incidentSolarMultiplierSchedule() const { + return getImpl()->incidentSolarMultiplierSchedule(); + } + + bool SurfacePropertyIncidentSolarMultiplier::setSubSurface(const SubSurface& subSurface) { + return getImpl()->setSubSurface(subSurface); + } + + bool SurfacePropertyIncidentSolarMultiplier::setIncidentSolarMultiplier(double incidentSolarMultiplier) { + return getImpl()->setIncidentSolarMultiplier(incidentSolarMultiplier); + } + + bool SurfacePropertyIncidentSolarMultiplier::setIncidentSolarMultiplierSchedule(Schedule& schedule) { + return getImpl()->setIncidentSolarMultiplierSchedule(schedule); + } + + void SurfacePropertyIncidentSolarMultiplier::resetIncidentSolarMultiplierSchedule() { + getImpl()->resetIncidentSolarMultiplierSchedule(); + } + + /// @cond + SurfacePropertyIncidentSolarMultiplier::SurfacePropertyIncidentSolarMultiplier( + std::shared_ptr impl) + : ModelObject(std::move(impl)) {} + /// @endcond + +} // namespace model +} // namespace openstudio diff --git a/src/model/SurfacePropertyIncidentSolarMultiplier.hpp b/src/model/SurfacePropertyIncidentSolarMultiplier.hpp new file mode 100644 index 0000000000..88b13ec320 --- /dev/null +++ b/src/model/SurfacePropertyIncidentSolarMultiplier.hpp @@ -0,0 +1,114 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +* following conditions are met: +* +* (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following +* disclaimer. +* +* (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided with the distribution. +* +* (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products +* derived from this software without specific prior written permission from the respective party. +* +* (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works +* may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior +* written permission from Alliance for Sustainable Energy, LLC. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED +* STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +***********************************************************************************************************************/ + +#ifndef MODEL_SURFACEPROPERTYINCIDENTSOLARMULTIPLIER_HPP +#define MODEL_SURFACEPROPERTYINCIDENTSOLARMULTIPLIER_HPP + +#include +#include "ModelObject.hpp" + +namespace openstudio { + +namespace model { + + class SubSurface; + class Schedule; + + namespace detail { + + class SurfacePropertyIncidentSolarMultiplier_Impl; + + } // namespace detail + + /** SurfacePropertyIncidentSolarMultiplier is a ModelObject that wraps the OpenStudio IDD object 'OS:SurfaceProperty:IncidentSolarMultiplier'. */ + class MODEL_API SurfacePropertyIncidentSolarMultiplier : public ModelObject + { + public: + /** @name Constructors and Destructors */ + //@{ + + explicit SurfacePropertyIncidentSolarMultiplier(const SubSurface& subSurface); + + virtual ~SurfacePropertyIncidentSolarMultiplier() = default; + + //@} + + static IddObjectType iddObjectType(); + + /** @name Getters */ + //@{ + + SubSurface subSurface() const; + + double incidentSolarMultiplier() const; + + boost::optional incidentSolarMultiplierSchedule() const; + + //@} + /** @name Setters */ + //@{ + + bool setSubSurface(const SubSurface& subSurface); + + bool setIncidentSolarMultiplier(double incidentSolarMultiplier); + + bool setIncidentSolarMultiplierSchedule(Schedule& schedule); + + void resetIncidentSolarMultiplierSchedule(); + + //@} + /** @name Other */ + //@{ + + //@} + protected: + /// @cond + using ImplType = detail::SurfacePropertyIncidentSolarMultiplier_Impl; + + explicit SurfacePropertyIncidentSolarMultiplier(std::shared_ptr impl); + + friend class detail::SurfacePropertyIncidentSolarMultiplier_Impl; + friend class Model; + friend class IdfObject; + friend class openstudio::detail::IdfObject_Impl; + /// @endcond + private: + REGISTER_LOGGER("openstudio.model.SurfacePropertyIncidentSolarMultiplier"); + }; + + /** \relates SurfacePropertyIncidentSolarMultiplier*/ + using OptionalSurfacePropertyIncidentSolarMultiplier = boost::optional; + + /** \relates SurfacePropertyIncidentSolarMultiplier*/ + using SurfacePropertyIncidentSolarMultiplierVector = std::vector; + +} // namespace model +} // namespace openstudio + +#endif // MODEL_SURFACEPROPERTYINCIDENTSOLARMULTIPLIER_HPP diff --git a/src/model/SurfacePropertyIncidentSolarMultiplier_Impl.hpp b/src/model/SurfacePropertyIncidentSolarMultiplier_Impl.hpp new file mode 100644 index 0000000000..34b58ca9e6 --- /dev/null +++ b/src/model/SurfacePropertyIncidentSolarMultiplier_Impl.hpp @@ -0,0 +1,108 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +* following conditions are met: +* +* (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following +* disclaimer. +* +* (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided with the distribution. +* +* (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products +* derived from this software without specific prior written permission from the respective party. +* +* (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works +* may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior +* written permission from Alliance for Sustainable Energy, LLC. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED +* STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +***********************************************************************************************************************/ + +#ifndef MODEL_SURFACEPROPERTYINCIDENTSOLARMULTIPLIER_IMPL_HPP +#define MODEL_SURFACEPROPERTYINCIDENTSOLARMULTIPLIER_IMPL_HPP + +#include +#include "ModelObject_Impl.hpp" + +namespace openstudio { +namespace model { + + class SubSurface; + class Schedule; + + namespace detail { + + /** SurfacePropertyIncidentSolarMultiplier_Impl is a ModelObject_Impl that is the implementation class for SurfacePropertyIncidentSolarMultiplier.*/ + class MODEL_API SurfacePropertyIncidentSolarMultiplier_Impl : public ModelObject_Impl + { + public: + /** @name Constructors and Destructors */ + //@{ + + SurfacePropertyIncidentSolarMultiplier_Impl(const IdfObject& idfObject, Model_Impl* model, bool keepHandle); + + SurfacePropertyIncidentSolarMultiplier_Impl(const openstudio::detail::WorkspaceObject_Impl& other, Model_Impl* model, bool keepHandle); + + SurfacePropertyIncidentSolarMultiplier_Impl(const SurfacePropertyIncidentSolarMultiplier_Impl& other, Model_Impl* model, bool keepHandle); + + virtual ~SurfacePropertyIncidentSolarMultiplier_Impl() = default; + + //@} + /** @name Virtual Methods */ + //@{ + + virtual const std::vector& outputVariableNames() const override; + + virtual IddObjectType iddObjectType() const override; + + virtual std::vector getScheduleTypeKeys(const Schedule& schedule) const override; + + //@} + /** @name Getters */ + //@{ + + SubSurface subSurface() const; + + double incidentSolarMultiplier() const; + + boost::optional incidentSolarMultiplierSchedule() const; + + //@} + /** @name Setters */ + //@{ + + bool setSubSurface(const SubSurface& subSurface); + + bool setIncidentSolarMultiplier(double incidentSolarMultiplier); + + bool setIncidentSolarMultiplierSchedule(Schedule& schedule); + + void resetIncidentSolarMultiplierSchedule(); + + //@} + /** @name Other */ + //@{ + + //@} + protected: + private: + REGISTER_LOGGER("openstudio.model.SurfacePropertyIncidentSolarMultiplier"); + + boost::optional optionalSubSurface() const; + }; + + } // namespace detail + +} // namespace model +} // namespace openstudio + +#endif // MODEL_SURFACEPROPERTYINCIDENTSOLARMULTIPLIER_IMPL_HPP diff --git a/src/model/SurfacePropertyLocalEnvironment.cpp b/src/model/SurfacePropertyLocalEnvironment.cpp index 218e242e40..ee70094e0d 100644 --- a/src/model/SurfacePropertyLocalEnvironment.cpp +++ b/src/model/SurfacePropertyLocalEnvironment.cpp @@ -42,6 +42,8 @@ #include "SurfacePropertySurroundingSurfaces.hpp" #include "SurfacePropertySurroundingSurfaces_Impl.hpp" +#include "SurfacePropertyGroundSurfaces.hpp" +#include "SurfacePropertyGroundSurfaces_Impl.hpp" //#include "OutdoorAirNode.hpp" // #include "OutdoorAirNode_Impl.hpp" #include "ScheduleTypeLimits.hpp" @@ -126,6 +128,11 @@ namespace model { OS_SurfaceProperty_LocalEnvironmentFields::SurroundingSurfacesObjectName); } + boost::optional SurfacePropertyLocalEnvironment_Impl::surfacePropertyGroundSurfaces() const { + return getObject().getModelObjectTarget( + OS_SurfaceProperty_LocalEnvironmentFields::GroundSurfacesObjectName); + } + bool SurfacePropertyLocalEnvironment_Impl::setExteriorSurface(const PlanarSurface& surface) { boost::optional currentLocalEnv; @@ -172,6 +179,16 @@ namespace model { OS_ASSERT(result); } + bool SurfacePropertyLocalEnvironment_Impl::setSurfacePropertyGroundSurfaces(const SurfacePropertyGroundSurfaces& surfacePropertyGroundSurfaces) { + bool result = setPointer(OS_SurfaceProperty_LocalEnvironmentFields::GroundSurfacesObjectName, surfacePropertyGroundSurfaces.handle()); + return result; + } + + void SurfacePropertyLocalEnvironment_Impl::resetSurfacePropertyGroundSurfaces() { + bool result = setString(OS_SurfaceProperty_LocalEnvironmentFields::GroundSurfacesObjectName, ""); + OS_ASSERT(result); + } + //boost::optional SurfacePropertyLocalEnvironment_Impl::outdoorAirNode() const { //return getObject().getModelObjectTarget(OS_SurfaceProperty_LocalEnvironmentFields::OutdoorAirNodeName); //} @@ -234,6 +251,10 @@ namespace model { return getImpl()->surfacePropertySurroundingSurfaces(); } + boost::optional SurfacePropertyLocalEnvironment::surfacePropertyGroundSurfaces() const { + return getImpl()->surfacePropertyGroundSurfaces(); + } + bool SurfacePropertyLocalEnvironment::setExteriorSurface(const PlanarSurface& surface) { return getImpl()->setExteriorSurface(surface); } @@ -255,6 +276,14 @@ namespace model { getImpl()->resetSurfacePropertySurroundingSurfaces(); } + bool SurfacePropertyLocalEnvironment::setSurfacePropertyGroundSurfaces(const SurfacePropertyGroundSurfaces& surfacePropertyGroundSurfaces) { + return getImpl()->setSurfacePropertyGroundSurfaces(surfacePropertyGroundSurfaces); + } + + void SurfacePropertyLocalEnvironment::resetSurfacePropertyGroundSurfaces() { + getImpl()->resetSurfacePropertyGroundSurfaces(); + } + //boost::optional SurfacePropertyLocalEnvironment::outdoorAirNode() const { //return getImpl()->outdoorAirNode(); //} diff --git a/src/model/SurfacePropertyLocalEnvironment.hpp b/src/model/SurfacePropertyLocalEnvironment.hpp index a609d88614..7802114f5b 100644 --- a/src/model/SurfacePropertyLocalEnvironment.hpp +++ b/src/model/SurfacePropertyLocalEnvironment.hpp @@ -41,6 +41,7 @@ namespace model { class PlanarSurface; class Schedule; class SurfacePropertySurroundingSurfaces; + class SurfacePropertyGroundSurfaces; // class OutdoorAirNode; namespace detail { @@ -76,6 +77,8 @@ namespace model { boost::optional surfacePropertySurroundingSurfaces() const; + boost::optional surfacePropertyGroundSurfaces() const; + // boost::optional outdoorAirNode() const; //@} @@ -92,6 +95,9 @@ namespace model { bool setSurfacePropertySurroundingSurfaces(const SurfacePropertySurroundingSurfaces& surfacePropertySurroundingSurfaces); void resetSurfacePropertySurroundingSurfaces(); + bool setSurfacePropertyGroundSurfaces(const SurfacePropertyGroundSurfaces& surfacePropertyGroundSurfaces); + void resetSurfacePropertyGroundSurfaces(); + // bool setOutdoorAirNode(const OutdoorAirNode& outdoorAirNode); // void resetOutdoorAirNode(); diff --git a/src/model/SurfacePropertyLocalEnvironment_Impl.hpp b/src/model/SurfacePropertyLocalEnvironment_Impl.hpp index 99df20e6ff..0ed0adeef1 100644 --- a/src/model/SurfacePropertyLocalEnvironment_Impl.hpp +++ b/src/model/SurfacePropertyLocalEnvironment_Impl.hpp @@ -41,6 +41,7 @@ namespace model { class SubSurface; class Schedule; class SurfacePropertySurroundingSurfaces; + class SurfacePropertyGroundSurfaces; // class OutdoorAirNode; namespace detail { @@ -82,6 +83,8 @@ namespace model { boost::optional surfacePropertySurroundingSurfaces() const; + boost::optional surfacePropertyGroundSurfaces() const; + // boost::optional outdoorAirNode() const; //@} @@ -96,6 +99,9 @@ namespace model { bool setSurfacePropertySurroundingSurfaces(const SurfacePropertySurroundingSurfaces& surfacePropertySurroundingSurfaces); void resetSurfacePropertySurroundingSurfaces(); + bool setSurfacePropertyGroundSurfaces(const SurfacePropertyGroundSurfaces& surfacePropertyGroundSurfaces); + void resetSurfacePropertyGroundSurfaces(); + // bool setOutdoorAirNode(const OutdoorAirNode& outdoorAirNode); // void resetOutdoorAirNode(); diff --git a/src/model/SurfacePropertySurroundingSurfaces.cpp b/src/model/SurfacePropertySurroundingSurfaces.cpp index 6a46eadbe8..9c9b50fef0 100644 --- a/src/model/SurfacePropertySurroundingSurfaces.cpp +++ b/src/model/SurfacePropertySurroundingSurfaces.cpp @@ -117,14 +117,38 @@ namespace model { std::vector SurfacePropertySurroundingSurfaces_Impl::getScheduleTypeKeys(const Schedule& schedule) const { std::vector result; - UnsignedVector fieldIndices = getSourceIndices(schedule.handle()); - UnsignedVector::const_iterator b(fieldIndices.begin()), e(fieldIndices.end()); - if (std::find(b, e, OS_SurfaceProperty_SurroundingSurfacesFields::SkyTemperatureScheduleName) != e) { - result.emplace_back("SurfacePropertySurroundingSurfaces", "Sky Temperature"); + + { + UnsignedVector fieldIndices = getSourceIndices(schedule.handle()); + UnsignedVector::const_iterator b(fieldIndices.begin()); + UnsignedVector::const_iterator e(fieldIndices.end()); + if (std::find(b, e, OS_SurfaceProperty_SurroundingSurfacesFields::SkyTemperatureScheduleName) != e) { + result.emplace_back("SurfacePropertySurroundingSurfaces", "Sky Temperature"); + } + if (std::find(b, e, OS_SurfaceProperty_SurroundingSurfacesFields::GroundTemperatureScheduleName) != e) { + result.emplace_back("SurfacePropertySurroundingSurfaces", "Ground Temperature"); + } } - if (std::find(b, e, OS_SurfaceProperty_SurroundingSurfacesFields::GroundTemperatureScheduleName) != e) { - result.emplace_back("SurfacePropertySurroundingSurfaces", "Ground Temperature"); + + { + // This is unusual, but there is also a schedule in the Extensible Fields + UnsignedVector fieldIndices; + for (const ModelExtensibleGroup& group : castVector(extensibleGroups())) { + UnsignedVector thisFieldIndices = group.getSourceFieldIndices(schedule.handle()); + fieldIndices.insert(fieldIndices.end(), thisFieldIndices.begin(), thisFieldIndices.end()); + } + + // Make unique, have to sort before calling unique, unique only works on consecutive elements + std::sort(fieldIndices.begin(), fieldIndices.end()); + fieldIndices.erase(std::unique(fieldIndices.begin(), fieldIndices.end()), fieldIndices.end()); + + UnsignedVector::const_iterator b(fieldIndices.begin()); + UnsignedVector::const_iterator e(fieldIndices.end()); + if (std::find(b, e, OS_SurfaceProperty_SurroundingSurfacesExtensibleFields::SurroundingSurfaceTemperatureScheduleName) != e) { + result.emplace_back("SurfacePropertySurroundingSurfaces", "Surrounding Surface Temperature Schedule"); + } } + return result; } diff --git a/src/model/test/SurfacePropertyGroundSurfaces_GTest.cpp b/src/model/test/SurfacePropertyGroundSurfaces_GTest.cpp new file mode 100644 index 0000000000..52ce324246 --- /dev/null +++ b/src/model/test/SurfacePropertyGroundSurfaces_GTest.cpp @@ -0,0 +1,175 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +* following conditions are met: +* +* (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following +* disclaimer. +* +* (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided with the distribution. +* +* (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products +* derived from this software without specific prior written permission from the respective party. +* +* (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works +* may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior +* written permission from Alliance for Sustainable Energy, LLC. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED +* STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +***********************************************************************************************************************/ + +#include "ModelFixture.hpp" + +#include "../SurfacePropertyGroundSurfaces.hpp" +#include "../SurfacePropertyGroundSurfaces_Impl.hpp" +#include "../ScheduleConstant.hpp" + +using namespace openstudio; +using namespace openstudio::model; + +TEST_F(ModelFixture, SurfacePropertyGroundSurfaces_GettersSetters) { + Model m; + + ScheduleConstant tempSch(m); + tempSch.setValue(25.0); + ScheduleConstant reflectanceSch(m); + reflectanceSch.setValue(1.0); + + { + // Wrong viewFactor (0 to 1) + EXPECT_THROW(GroundSurfaceGroup("External Surface", 1.2), openstudio::Exception); + EXPECT_NO_THROW(GroundSurfaceGroup("External Surface", 0.2)); + + EXPECT_NO_THROW(GroundSurfaceGroup("External Surface", 0.2, tempSch)); + + EXPECT_NO_THROW(GroundSurfaceGroup("External Surface", 0.2, tempSch, reflectanceSch)); + } + + SurfacePropertyGroundSurfaces sp(m); + + EXPECT_EQ(0, sp.numberofGroundSurfaceGroups()); + EXPECT_TRUE(sp.addGroundSurfaceGroup("External Surface 1", 0.2, tempSch, reflectanceSch)); + EXPECT_EQ(1, sp.numberofGroundSurfaceGroups()); + + auto group2 = GroundSurfaceGroup("External Surface 2", 0.3, tempSch, reflectanceSch); + EXPECT_TRUE(sp.addGroundSurfaceGroup(group2)); + EXPECT_EQ(2, sp.numberofGroundSurfaceGroups()); + + ScheduleConstant tempSch2(m); + tempSch2.setValue(35.0); + auto group3 = GroundSurfaceGroup("External Surface 3", 0.4, tempSch2); + EXPECT_TRUE(sp.addGroundSurfaceGroup(group3)); + EXPECT_EQ(3, sp.numberofGroundSurfaceGroups()); + + boost::optional group_ = sp.getGroundSurfaceGroup(1U); + ASSERT_TRUE(group_); + EXPECT_EQ("External Surface 2", group_->groundSurfaceName()); + EXPECT_EQ(0.3, group_->viewFactor()); + ASSERT_TRUE(group_->temperatureSchedule()); + EXPECT_EQ(tempSch, group_->temperatureSchedule().get()); + ASSERT_TRUE(group_->reflectanceSchedule()); + EXPECT_EQ(reflectanceSch, group_->reflectanceSchedule().get()); + + // Test that you cannot add the same group twice (based on Surface Name), but that instead it'll overwrite the values + auto group2bis = GroundSurfaceGroup("External Surface 2", 0.45, tempSch2); + // Test that we can locate an existing ViewFactor correctly (comparing on to/from only, not viewFactor value) + boost::optional _existingIndex = sp.groundSurfaceGroupIndex(group2bis); + ASSERT_TRUE(_existingIndex); + EXPECT_EQ(1U, _existingIndex.get()); + // Test with the std::string version + _existingIndex = sp.groundSurfaceGroupIndex("External Surface 2"); + ASSERT_TRUE(_existingIndex); + EXPECT_EQ(1U, _existingIndex.get()); + + // Now call add, which should jut override it + EXPECT_TRUE(sp.addGroundSurfaceGroup(group2bis)); + // Should still have the same number + EXPECT_EQ(3, sp.numberofGroundSurfaceGroups()); + + // Retrieve it again, making sure it changed only the values viewFactor and Schedule + boost::optional group2_ = sp.getGroundSurfaceGroup(1U); + ASSERT_TRUE(group2_); + EXPECT_EQ("External Surface 2", group2_->groundSurfaceName()); + EXPECT_EQ(0.45, group2_->viewFactor()); + ASSERT_TRUE(group2_->temperatureSchedule()); + EXPECT_EQ(tempSch2, group2_->temperatureSchedule().get()); + EXPECT_FALSE(group2_->reflectanceSchedule()); + + // Via the overloaded method + EXPECT_TRUE(sp.addGroundSurfaceGroup("External Surface 2", 0.32, tempSch, reflectanceSch)); + boost::optional group3_ = sp.getGroundSurfaceGroup(1U); + ASSERT_TRUE(group3_); + EXPECT_EQ("External Surface 2", group3_->groundSurfaceName()); + EXPECT_EQ(0.32, group3_->viewFactor()); + ASSERT_TRUE(group3_->temperatureSchedule()); + EXPECT_EQ(tempSch, group3_->temperatureSchedule().get()); + ASSERT_TRUE(group3_->reflectanceSchedule()); + EXPECT_EQ(reflectanceSch, group3_->reflectanceSchedule().get()); + + // Test that you cannot get a group by an index that's too high + EXPECT_FALSE(sp.getGroundSurfaceGroup(sp.numberofGroundSurfaceGroups())); + + // Test that you cannot find a group if it doesn't exist + auto groupother = GroundSurfaceGroup("Another surface", 0.45, tempSch2); + EXPECT_FALSE(sp.groundSurfaceGroupIndex(groupother)); + + // Remove a viewFactor + EXPECT_FALSE(sp.removeGroundSurfaceGroup(1000)); + EXPECT_EQ(3, sp.numberofGroundSurfaceGroups()); + + EXPECT_TRUE(sp.removeGroundSurfaceGroup(1)); + EXPECT_EQ(2, sp.numberofGroundSurfaceGroups()); + + // check that remaining blocks moved correctly + std::vector groups = sp.groundSurfaceGroups(); + EXPECT_EQ(2U, groups.size()); + EXPECT_EQ("External Surface 1", groups[0].groundSurfaceName()); + EXPECT_EQ(0.2, groups[0].viewFactor()); + ASSERT_TRUE(groups[0].temperatureSchedule()); + EXPECT_EQ(tempSch, groups[0].temperatureSchedule().get()); + ASSERT_TRUE(groups[0].reflectanceSchedule()); + EXPECT_EQ(reflectanceSch, groups[0].reflectanceSchedule().get()); + + EXPECT_EQ("External Surface 3", groups[1].groundSurfaceName()); + EXPECT_EQ(0.4, groups[1].viewFactor()); + ASSERT_TRUE(groups[1].temperatureSchedule()); + EXPECT_EQ(tempSch2, groups[1].temperatureSchedule().get()); + EXPECT_FALSE(groups[1].reflectanceSchedule()); + + // more remove checking + sp.removeAllGroundSurfaceGroups(); + EXPECT_EQ(0, sp.numberofGroundSurfaceGroups()); + EXPECT_FALSE(sp.removeGroundSurfaceGroup(0)); + EXPECT_EQ(0, sp.numberofGroundSurfaceGroups()); + + // Via a vector + EXPECT_TRUE(sp.addGroundSurfaceGroups({group2bis, groupother, group3})); + groups = sp.groundSurfaceGroups(); + EXPECT_EQ(3U, groups.size()); + EXPECT_EQ(group2bis.groundSurfaceName(), groups[0].groundSurfaceName()); + EXPECT_EQ(group2bis.viewFactor(), groups[0].viewFactor()); + ASSERT_TRUE(groups[0].temperatureSchedule()); + EXPECT_EQ(group2bis.temperatureSchedule().get(), groups[0].temperatureSchedule().get()); + EXPECT_FALSE(groups[0].reflectanceSchedule()); + + EXPECT_EQ(groupother.groundSurfaceName(), groups[1].groundSurfaceName()); + EXPECT_EQ(groupother.viewFactor(), groups[1].viewFactor()); + ASSERT_TRUE(groups[1].temperatureSchedule()); + EXPECT_EQ(groupother.temperatureSchedule().get(), groups[1].temperatureSchedule().get()); + EXPECT_FALSE(groups[1].reflectanceSchedule()); + + EXPECT_EQ(group3.groundSurfaceName(), groups[2].groundSurfaceName()); + EXPECT_EQ(group3.viewFactor(), groups[2].viewFactor()); + ASSERT_TRUE(groups[2].temperatureSchedule()); + EXPECT_EQ(group3.temperatureSchedule().get(), groups[2].temperatureSchedule().get()); + EXPECT_FALSE(groups[2].reflectanceSchedule()); +} diff --git a/src/model/test/SurfacePropertyIncidentSolarMultiplier_GTest.cpp b/src/model/test/SurfacePropertyIncidentSolarMultiplier_GTest.cpp new file mode 100644 index 0000000000..c48970adec --- /dev/null +++ b/src/model/test/SurfacePropertyIncidentSolarMultiplier_GTest.cpp @@ -0,0 +1,78 @@ +/*********************************************************************************************************************** +* OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +* following conditions are met: +* +* (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following +* disclaimer. +* +* (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided with the distribution. +* +* (3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse or promote products +* derived from this software without specific prior written permission from the respective party. +* +* (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works +* may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior +* written permission from Alliance for Sustainable Energy, LLC. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED +* STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +***********************************************************************************************************************/ + +#include "ModelFixture.hpp" + +#include "../SurfacePropertyIncidentSolarMultiplier.hpp" +#include "../SurfacePropertyIncidentSolarMultiplier_Impl.hpp" + +#include "../SubSurface.hpp" + +#include "../Schedule.hpp" +#include "../ScheduleConstant.hpp" + +#include "../../utilities/geometry/Point3d.hpp" + +using namespace openstudio; +using namespace openstudio::model; + +TEST_F(ModelFixture, SurfacePropertyIncidentSolarMultiplier_GettersSetters) { + Model m; + + std::vector vertices{{0, 0, 1}, {0, 0, 0}, {1, 0, 0}, {1, 0, 1}}; + + SubSurface ss(vertices, m); + + SurfacePropertyIncidentSolarMultiplier sp(ss); + + EXPECT_EQ(1, sp.incidentSolarMultiplier()); + EXPECT_FALSE(sp.incidentSolarMultiplierSchedule()); + EXPECT_EQ(ss, sp.subSurface()); + Schedule alwaysOnContinuous = m.alwaysOnContinuousSchedule(); + + // Surface Name: Required Object + SubSurface ss2(vertices, m); + EXPECT_TRUE(sp.setSubSurface(ss2)); + EXPECT_EQ(ss2, sp.subSurface()); + ASSERT_TRUE(ss2.surfacePropertyIncidentSolarMultiplier()); + EXPECT_EQ(sp, ss2.surfacePropertyIncidentSolarMultiplier().get()); + + // Incident Solar Multiplier: Required Double + EXPECT_TRUE(sp.setIncidentSolarMultiplier(0.75)); + EXPECT_EQ(0.75, sp.incidentSolarMultiplier()); + // Bad Value + EXPECT_FALSE(sp.setIncidentSolarMultiplier(-10.0)); + EXPECT_EQ(0.75, sp.incidentSolarMultiplier()); + + // Incident Solar Multiplier Schedule Name: Optional Object + ScheduleConstant sch(m); + EXPECT_TRUE(sp.setIncidentSolarMultiplierSchedule(sch)); + ASSERT_TRUE(sp.incidentSolarMultiplierSchedule()); + EXPECT_EQ(sch, sp.incidentSolarMultiplierSchedule().get()); +} diff --git a/src/model/test/SurfacePropertyLocalEnvironment_GTest.cpp b/src/model/test/SurfacePropertyLocalEnvironment_GTest.cpp index 1e4675f11f..7c05fb1bdd 100644 --- a/src/model/test/SurfacePropertyLocalEnvironment_GTest.cpp +++ b/src/model/test/SurfacePropertyLocalEnvironment_GTest.cpp @@ -36,6 +36,7 @@ #include "../Schedule.hpp" #include "../ScheduleConstant.hpp" #include "../SurfacePropertySurroundingSurfaces.hpp" +#include "../SurfacePropertyGroundSurfaces.hpp" #include "../../utilities/geometry/Point3d.hpp" @@ -88,19 +89,38 @@ TEST_F(ModelFixture, SurfacePropertyLocalEnvironment_GettersSetters) { EXPECT_FALSE(surfacePropertyLocalEnvironment.externalShadingFractionSchedule()); // Surrounding Surfaces Object Name: Optional Object - EXPECT_FALSE(surfacePropertyLocalEnvironment.surfacePropertySurroundingSurfaces()); - SurfacePropertySurroundingSurfaces sp(m); - EXPECT_FALSE(sp.surfacePropertyLocalEnvironment()); - - EXPECT_TRUE(surfacePropertyLocalEnvironment.setSurfacePropertySurroundingSurfaces(sp)); - ASSERT_TRUE(surfacePropertyLocalEnvironment.surfacePropertySurroundingSurfaces()); - EXPECT_EQ(sp, surfacePropertyLocalEnvironment.surfacePropertySurroundingSurfaces().get()); - - ASSERT_TRUE(sp.surfacePropertyLocalEnvironment()); - EXPECT_EQ(surfacePropertyLocalEnvironment, sp.surfacePropertyLocalEnvironment().get()); - - surfacePropertyLocalEnvironment.resetSurfacePropertySurroundingSurfaces(); - EXPECT_FALSE(surfacePropertyLocalEnvironment.surfacePropertySurroundingSurfaces()); + { + EXPECT_FALSE(surfacePropertyLocalEnvironment.surfacePropertySurroundingSurfaces()); + SurfacePropertySurroundingSurfaces sp(m); + EXPECT_FALSE(sp.surfacePropertyLocalEnvironment()); + + EXPECT_TRUE(surfacePropertyLocalEnvironment.setSurfacePropertySurroundingSurfaces(sp)); + ASSERT_TRUE(surfacePropertyLocalEnvironment.surfacePropertySurroundingSurfaces()); + EXPECT_EQ(sp, surfacePropertyLocalEnvironment.surfacePropertySurroundingSurfaces().get()); + + ASSERT_TRUE(sp.surfacePropertyLocalEnvironment()); + EXPECT_EQ(surfacePropertyLocalEnvironment, sp.surfacePropertyLocalEnvironment().get()); + + surfacePropertyLocalEnvironment.resetSurfacePropertySurroundingSurfaces(); + EXPECT_FALSE(surfacePropertyLocalEnvironment.surfacePropertySurroundingSurfaces()); + } + + // Ground Surfaces Object Name: Optional Object + { + EXPECT_FALSE(surfacePropertyLocalEnvironment.surfacePropertyGroundSurfaces()); + SurfacePropertyGroundSurfaces sp(m); + EXPECT_FALSE(sp.surfacePropertyLocalEnvironment()); + + EXPECT_TRUE(surfacePropertyLocalEnvironment.setSurfacePropertyGroundSurfaces(sp)); + ASSERT_TRUE(surfacePropertyLocalEnvironment.surfacePropertyGroundSurfaces()); + EXPECT_EQ(sp, surfacePropertyLocalEnvironment.surfacePropertyGroundSurfaces().get()); + + ASSERT_TRUE(sp.surfacePropertyLocalEnvironment()); + EXPECT_EQ(surfacePropertyLocalEnvironment, sp.surfacePropertyLocalEnvironment().get()); + + surfacePropertyLocalEnvironment.resetSurfacePropertyGroundSurfaces(); + EXPECT_FALSE(surfacePropertyLocalEnvironment.surfacePropertyGroundSurfaces()); + } // It should also accept a SubSurface SubSurface subSurface(points2, m);