Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
053a7bf
Add new surface fraction fields for radiant convective baseboard elec…
joseph-robertson Jan 26, 2026
48060e0
Add getters and setters for radiant convective baseboard electric.
joseph-robertson Jan 26, 2026
154e1e4
Update ft for new radiant convective baseboard electric fields.
joseph-robertson Jan 26, 2026
3cda5ef
Merge branch 'bump-version' into rad-conv-surf-fracs
joseph-robertson Jan 26, 2026
0d1956f
Add vt and test.
joseph-robertson Jan 26, 2026
0292be7
Formatting.
joseph-robertson Jan 26, 2026
57c3dd5
Add getters and setters for radiant convective baseboard water and co…
joseph-robertson Jan 26, 2026
7dc1730
Update ft for new radiant convective baseboard water and cooling pane…
joseph-robertson Jan 26, 2026
c28fd74
Add vt for radiant convective baseboard water and cooling panel, and …
joseph-robertson Jan 26, 2026
06e05fc
Formatting.
joseph-robertson Jan 26, 2026
938d12b
Add model tests, and new missing ft test files.
joseph-robertson Jan 27, 2026
f037eb9
Formatting.
joseph-robertson Jan 27, 2026
a2529b4
Update and fill out remainder of ft test files.
joseph-robertson Jan 27, 2026
01a6850
Remove extra includes.
joseph-robertson Jan 29, 2026
8de63e7
Typos and missing includes in ft test files.
joseph-robertson Jan 30, 2026
885d73c
Typos in extensible group sections of ft tests.
joseph-robertson Jan 31, 2026
3452381
Fix minor typos in new baseboard radiant convective ft tests.
joseph-robertson Feb 2, 2026
db22fed
Comment out surface name check in ft tests since order not determinis…
joseph-robertson Feb 3, 2026
618a214
Try using surfaces getter for same surface order.
joseph-robertson Feb 3, 2026
db49e41
Simplify ft tests for extensible groups.
joseph-robertson Feb 3, 2026
1e7f587
Missing cast as WorkspaceExtensibleGroup.
joseph-robertson Feb 4, 2026
6e4bffb
Expect near, not equal.
joseph-robertson Feb 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 53 additions & 8 deletions resources/model/OpenStudio.idd
Original file line number Diff line number Diff line change
Expand Up @@ -31809,7 +31809,22 @@ OS:ZoneHVAC:Baseboard:RadiantConvective:Water,
\type real
\minimum 0
\maximum 1
N2; \field Fraction of Radiant Energy Incident on People
N2, \field Fraction of Radiant Energy Incident on People
\required-field
\type real
\minimum 0
\maximum 1
N3, \field Fraction of Radiant Energy to Floor Surfaces
\required-field
\type real
\minimum 0
\maximum 1
N4, \field Fraction of Radiant Energy to Wall Surfaces
\required-field
\type real
\minimum 0
\maximum 1
N5; \field Fraction of Radiant Energy to Ceiling Surfaces
\required-field
\type real
\minimum 0
Expand Down Expand Up @@ -31857,34 +31872,64 @@ OS:ZoneHVAC:Baseboard:RadiantConvective:Electric,
\type real
\minimum 0
\maximum 1
N6; \field Fraction of Radiant Energy Incident on People
N6, \field Fraction of Radiant Energy Incident on People
\required-field
\type real
\minimum 0
\maximum 1
N7, \field Fraction of Radiant Energy to Floor Surfaces
\required-field
\type real
\minimum 0
\maximum 1
N8, \field Fraction of Radiant Energy to Wall Surfaces
\required-field
\type real
\minimum 0
\maximum 1
N9; \field Fraction of Radiant Energy to Ceiling Surfaces
\required-field
\type real
\minimum 0
\maximum 1

OS:ZoneHVAC:CoolingPanel:RadiantConvective:Water,
A1 , \field Handle
A1, \field Handle
\type handle
\required-field
A2 , \field Name
A2, \field Name
\required-field
\type alpha
\reference ConnectionObject
A3 , \field Availability Schedule Name
A3, \field Availability Schedule Name
\required-field
\type object-list
\object-list ScheduleNames
A4 , \field Cooling Coil Name
A4, \field Cooling Coil Name
\type object-list
\required-field
\object-list RadiantPanelCoolingCoil
N1 , \field Fraction Radiant
N1, \field Fraction Radiant
\required-field
\type real
\minimum 0
\maximum 1
N2, \field Fraction of Radiant Energy Incident on People
\required-field
\type real
\minimum 0
\maximum 1
N3, \field Fraction of Radiant Energy to Floor Surfaces
\required-field
\type real
\minimum 0
\maximum 1
N4, \field Fraction of Radiant Energy to Wall Surfaces
\required-field
\type real
\minimum 0
\maximum 1
N2 ; \field Fraction of Radiant Energy Incident on People
N5; \field Fraction of Radiant Energy to Ceiling Surfaces
\required-field
\type real
\minimum 0
Expand Down
2 changes: 2 additions & 0 deletions src/energyplus/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -862,7 +862,9 @@ set(${target_name}_test_src
Test/WaterHeaterStratified_GTest.cpp
Test/WaterUseConnections_GTest.cpp
Test/ZoneAirHeatBalanceAlgorithm_GTest.cpp
Test/ZoneHVACBaseboardRadiantConvectiveElectric_GTest.cpp
Test/ZoneHVACBaseboardRadiantConvectiveWater_GTest.cpp
Test/ZoneHVACCoolingPanelRadiantConvectiveWater_GTest.cpp
Test/ZoneHVACEvaporativeCoolerUnit_GTest.cpp
Test/ZoneHVACIdealLoadsAirSystem_GTest.cpp
Test/ZoneHVACLowTemperatureRadiantElectric_GTest.cpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,15 @@ namespace energyplus {
}
}

// Assume that 5% of what is not on people is on the floor
double fractionOnFloor = (1.0 - fractionofRadiantEnergyIncidentonPeople) * 0.05;
// Assume that 55% of what is not on people is on the walls
double fractionOnWall = (1.0 - fractionofRadiantEnergyIncidentonPeople) * 0.55;
// Assume that 40% of what is not on people is on the ceiling
double fractionOnCeiling = (1.0 - fractionofRadiantEnergyIncidentonPeople) * 0.40;
// SurfaceName
// FractionofRadiantEnergytoSurface
double fractionofRadiantEnergytoFloorSurfaces = modelObject.fractionofRadiantEnergytoFloorSurfaces();
double fractionofRadiantEnergytoWallSurfaces = modelObject.fractionofRadiantEnergytoWallSurfaces();
double fractionofRadiantEnergytoCeilingSurfaces = modelObject.fractionofRadiantEnergytoCeilingSurfaces();

double fractionOnFloor = (1.0 - fractionofRadiantEnergyIncidentonPeople) * fractionofRadiantEnergytoFloorSurfaces;
double fractionOnWall = (1.0 - fractionofRadiantEnergyIncidentonPeople) * fractionofRadiantEnergytoWallSurfaces;
double fractionOnCeiling = (1.0 - fractionofRadiantEnergyIncidentonPeople) * fractionofRadiantEnergytoCeilingSurfaces;
//loop through all the surfaces, adding them and their flow fractions (weighted per-area)
for (auto const& surface : surfaces) {
IdfExtensibleGroup group = idfObject.pushExtensibleGroup();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,15 @@ namespace energyplus {
}
}

// Assume that 5% of what is not on people is on the floor
double fractionOnFloor = (1.0 - fractionofRadiantEnergyIncidentonPeople) * 0.05;
// Assume that 55% of what is not on people is on the walls
double fractionOnWall = (1.0 - fractionofRadiantEnergyIncidentonPeople) * 0.55;
// Assume that 40% of what is not on people is on the ceiling
double fractionOnCeiling = (1.0 - fractionofRadiantEnergyIncidentonPeople) * 0.40;
// SurfaceName
// FractionofRadiantEnergytoSurface
double fractionofRadiantEnergytoFloorSurfaces = modelObject.fractionofRadiantEnergytoFloorSurfaces();
double fractionofRadiantEnergytoWallSurfaces = modelObject.fractionofRadiantEnergytoWallSurfaces();
double fractionofRadiantEnergytoCeilingSurfaces = modelObject.fractionofRadiantEnergytoCeilingSurfaces();

double fractionOnFloor = (1.0 - fractionofRadiantEnergyIncidentonPeople) * fractionofRadiantEnergytoFloorSurfaces;
double fractionOnWall = (1.0 - fractionofRadiantEnergyIncidentonPeople) * fractionofRadiantEnergytoWallSurfaces;
double fractionOnCeiling = (1.0 - fractionofRadiantEnergyIncidentonPeople) * fractionofRadiantEnergytoCeilingSurfaces;
//loop through all the surfaces, adding them and their flow fractions (weighted per-area)
for (auto const& surface : surfaces) {
IdfExtensibleGroup group = idfObject.pushExtensibleGroup();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,12 +167,15 @@ namespace energyplus {
}
}

// Assume that 5% of what is not on people is on the floor
double fractionOnFloor = (1.0 - fractionofRadiantEnergyIncidentonPeople) * 0.05;
// Assume that 55% of what is not on people is on the walls
double fractionOnWall = (1.0 - fractionofRadiantEnergyIncidentonPeople) * 0.55;
// Assume that 40% of what is not on people is on the ceiling
double fractionOnCeiling = (1.0 - fractionofRadiantEnergyIncidentonPeople) * 0.40;
// SurfaceName
// FractionofRadiantEnergytoSurface
double fractionofRadiantEnergytoFloorSurfaces = modelObject.fractionofRadiantEnergytoFloorSurfaces();
double fractionofRadiantEnergytoWallSurfaces = modelObject.fractionofRadiantEnergytoWallSurfaces();
double fractionofRadiantEnergytoCeilingSurfaces = modelObject.fractionofRadiantEnergytoCeilingSurfaces();

double fractionOnFloor = (1.0 - fractionofRadiantEnergyIncidentonPeople) * fractionofRadiantEnergytoFloorSurfaces;
double fractionOnWall = (1.0 - fractionofRadiantEnergyIncidentonPeople) * fractionofRadiantEnergytoWallSurfaces;
double fractionOnCeiling = (1.0 - fractionofRadiantEnergyIncidentonPeople) * fractionofRadiantEnergytoCeilingSurfaces;
//loop through all the surfaces, adding them and their flow fractions (weighted per-area)
for (auto const& surface : surfaces) {
IdfExtensibleGroup group = idfObject.pushExtensibleGroup();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/***********************************************************************************************************************
* OpenStudio(R), Copyright (c) Alliance for Energy Innovation, LLC.
* See also https://openstudio.net/license
***********************************************************************************************************************/

#include <gtest/gtest.h>
#include "EnergyPlusFixture.hpp"

#include "../ForwardTranslator.hpp"
#include "../ReverseTranslator.hpp"

#include "../../model/ZoneHVACBaseboardRadiantConvectiveElectric.hpp"
#include "../../model/ZoneHVACBaseboardRadiantConvectiveElectric_Impl.hpp"

#include "../../model/Model.hpp"
#include "../../model/HVACComponent.hpp"
#include "../../model/ThermalZone.hpp"
#include "../../model/Space.hpp"
#include "../../model/Surface.hpp"
#include "../../model/Schedule.hpp"

#include "../../utilities/idf/IdfFile.hpp"
#include "../../utilities/idf/Workspace.hpp"
#include "../../utilities/idf/IdfObject.hpp"
#include "../../utilities/idf/WorkspaceObject.hpp"
#include "../../utilities/idf/IdfExtensibleGroup.hpp"
#include "../../utilities/idf/WorkspaceExtensibleGroup.hpp"
#include "../../utilities/geometry/Point3d.hpp"

#include <utilities/idd/ZoneHVAC_Baseboard_RadiantConvective_Electric_FieldEnums.hxx>
#include <utilities/idd/BuildingSurface_Detailed_FieldEnums.hxx>
#include <utilities/idd/IddEnums.hxx>

using namespace openstudio::energyplus;
using namespace openstudio::model;
using namespace openstudio;

TEST_F(EnergyPlusFixture, ZoneHVACBaseboardRadiantConvectiveElectric) {
//make the example model
Model m = model::exampleModel();

ZoneHVACBaseboardRadiantConvectiveElectric baseboard(m);

Point3dVector floorPrint{
{0, 10, 0},
{10, 10, 0},
{10, 0, 0},
{0, 0, 0},
};
boost::optional<Space> space1 = Space::fromFloorPrint(floorPrint, 3, m);
ASSERT_TRUE(space1);
auto surfaces = space1->surfaces();
EXPECT_EQ(6u, surfaces.size());

// Space needs to be in a ThermalZone or it's not translated
ThermalZone z(m);
EXPECT_TRUE(space1->setThermalZone(z));

EXPECT_TRUE(baseboard.addToThermalZone(z));

// Some tweaks to disambiguate the ft tests later
baseboard.setName("My Baseboard");
EXPECT_TRUE(baseboard.setHeatingDesignCapacityMethod("CapacityPerFloorArea"));
EXPECT_TRUE(baseboard.setHeatingDesignCapacity(0));
EXPECT_TRUE(baseboard.setHeatingDesignCapacityPerFloorArea(100.0));
EXPECT_TRUE(baseboard.setFractionofAutosizedHeatingDesignCapacity(0));
EXPECT_TRUE(baseboard.setEfficiency(0.9));
EXPECT_TRUE(baseboard.setFractionRadiant(0.4));
EXPECT_TRUE(baseboard.setFractionofRadiantEnergyIncidentonPeople(0.35));
EXPECT_TRUE(baseboard.setFractionofRadiantEnergytoFloorSurfaces(0.41));
EXPECT_TRUE(baseboard.setFractionofRadiantEnergytoWallSurfaces(0.51));
EXPECT_TRUE(baseboard.setFractionofRadiantEnergytoCeilingSurfaces(0.61));

// Translate
ForwardTranslator ft;
Workspace w = ft.translateModel(m);

WorkspaceObjectVector idfBaseboards = w.getObjectsByType(IddObjectType::ZoneHVAC_Baseboard_RadiantConvective_Electric);
ASSERT_EQ(1u, idfBaseboards.size());
WorkspaceObject idfBaseboard(idfBaseboards[0]);

// Name
EXPECT_EQ(baseboard.nameString(), idfBaseboard.getString(ZoneHVAC_Baseboard_RadiantConvective_ElectricFields::Name).get());
// Availability Schedule Name
EXPECT_EQ(baseboard.availabilitySchedule().nameString(),
idfBaseboard.getString(ZoneHVAC_Baseboard_RadiantConvective_ElectricFields::AvailabilityScheduleName).get());
// Heating Design Capacity Method
EXPECT_EQ("CapacityPerFloorArea", idfBaseboard.getString(ZoneHVAC_Baseboard_RadiantConvective_ElectricFields::HeatingDesignCapacityMethod).get());
// Heating Design Capacity
EXPECT_EQ(0.0, idfBaseboard.getDouble(ZoneHVAC_Baseboard_RadiantConvective_ElectricFields::HeatingDesignCapacity).get());
// Heating Design Capacity Per Floor Area
EXPECT_EQ(100.0, idfBaseboard.getDouble(ZoneHVAC_Baseboard_RadiantConvective_ElectricFields::HeatingDesignCapacityPerFloorArea).get());
// Fraction of Autosized Heating Design Capacity
EXPECT_EQ(0.0, idfBaseboard.getDouble(ZoneHVAC_Baseboard_RadiantConvective_ElectricFields::FractionofAutosizedHeatingDesignCapacity).get());
// Efficiency
EXPECT_EQ(0.9, idfBaseboard.getDouble(ZoneHVAC_Baseboard_RadiantConvective_ElectricFields::Efficiency).get());
// Fraction Radiant
EXPECT_EQ(0.4, idfBaseboard.getDouble(ZoneHVAC_Baseboard_RadiantConvective_ElectricFields::FractionRadiant).get());
// Fraction of Radiant Energy Incident on People
EXPECT_EQ(0.35, idfBaseboard.getDouble(ZoneHVAC_Baseboard_RadiantConvective_ElectricFields::FractionofRadiantEnergyIncidentonPeople).get());

double totalAreaOfWallSurfaces = 4 * 10.0 * 10.0;
double totalAreaOfCeilingSurfaces = 1 * 10.0 * 10.0;
double totalAreaOfFloorSurfaces = 1 * 10.0 * 10.0;

double fractionOnFloor = (1.0 - 0.35) * 0.41;
double fractionOnWall = (1.0 - 0.35) * 0.51;
double fractionOnCeiling = (1.0 - 0.35) * 0.61;

// Surface 1 Name
// Fraction of Radiant Energy to Surface 1
EXPECT_EQ(surfaces.size(), idfBaseboard.numExtensibleGroups());
for (const auto& idf_eg : idfBaseboard.extensibleGroups()) {
auto eg = idf_eg.cast<WorkspaceExtensibleGroup>(); // Casting for getTarget
boost::optional<WorkspaceObject> idf_surf(eg.getTarget(ZoneHVAC_Baseboard_RadiantConvective_ElectricExtensibleFields::SurfaceName));
ASSERT_TRUE(idf_surf);
EXPECT_EQ(idf_surf->iddObject().type(), IddObjectType::BuildingSurface_Detailed);
std::string surfaceType = idf_surf->getString(BuildingSurface_DetailedFields::SurfaceType).get();
double fractionofRadiantEnergytoSurface =
eg.getDouble(ZoneHVAC_Baseboard_RadiantConvective_ElectricExtensibleFields::FractionofRadiantEnergytoSurface).get();
if (istringEqual(surfaceType, "Floor")) {
EXPECT_NEAR(100.0 / totalAreaOfFloorSurfaces * fractionOnFloor, fractionofRadiantEnergytoSurface, 0.0001);
} else if (istringEqual(surfaceType, "Roof") || istringEqual(surfaceType, "Ceiling")) {
EXPECT_NEAR(100.0 / totalAreaOfCeilingSurfaces * fractionOnCeiling, fractionofRadiantEnergytoSurface, 0.0001);
} else {
EXPECT_NEAR(100.0 / totalAreaOfWallSurfaces * fractionOnWall, fractionofRadiantEnergytoSurface, 0.0001);
}
}
}
Loading