Question-and-Answer Resource for the Building Energy Modeling Community
Get started with the Help page
Ask Your Question
2

How Do I set the "Field Set: Surface Name, Fraction of Radiant Energy to Surface" parameter for my "ZoneHVACCoolingPanelRadiantConvectiveWater" using OpenStudioSDK

asked 2026-01-20 16:49:38 -0500

chenkianwee's avatar

updated 2026-01-21 09:11:25 -0500

I am trying to model ZoneHVACCoolingPanelRadiantConvectiveWater, I am unable to find any functions to set the parameter "Field Set: Surface Name, Fraction of Radiant Energy to Surface" on the documentation. Has anyone done this before? I believe the ZoneHVACBaseboardRadiantConvectiveWater have similar parameters too. Thanks.

edit retag flag offensive close merge delete

Comments

1

@chenkianwee what simulation tool are you using? Please mention it in the title or body of your post, as well as add a tag so that others can provide better help. It seems like EnergyPlus based on object types that you mention, with possibly the OpenStudio SDK for "... any functions to set the parameter ...".

Aaron Boranian's avatar Aaron Boranian  ( 2026-01-21 07:43:30 -0500 )edit

I have added more details hopefully the question is much more clearer. Thanks !

chenkianwee's avatar chenkianwee  ( 2026-01-21 09:13:59 -0500 )edit

2 Answers

Sort by ยป oldest newest most voted
0

answered 2026-03-06 13:35:34 -0500

chenkianwee's avatar

For those that are working on radiant cooling panels modeling, I have written an energyplus measure codes to fix the issue.

def get_tzone_of_rad_clg_pnls(rad_pnls: list[openstudio.WorkspaceObject], workspace: openstudio.Workspace) -> dict:
            # get all rad pnl in the starting workspace
            rad_pnl_dicts = {}
            for rad_pnl in rad_pnls:
                rad_name_ = rad_pnl.getString(0)
                frac_rad_on_ppl_ = rad_pnl.getString(18)
                if rad_name_.is_initialized():
                    rad_name = rad_name_.get()
                    rad_pnl_dicts[rad_name] = {'idf_obj': rad_pnl}
                if frac_rad_on_ppl_.is_initialized():
                    frac_rad_on_ppl = float(frac_rad_on_ppl_.get())
                    rad_pnl_dicts[rad_name]['frac_rad_on_ppl'] = frac_rad_on_ppl

            # get all the zonehvac equip list
            rad_pnl_names = rad_pnl_dicts.keys()
            zhvac_equip_lss = workspace.getObjectsByType('ZoneHVAC:EquipmentList')
            for zhvac_equip_ls in zhvac_equip_lss:
                ext_grps = zhvac_equip_ls.extensibleGroups()
                for ext_grp in ext_grps:
                    zequip_obj_type = str(ext_grp.getString(0))
                    if zequip_obj_type == 'ZoneHVAC:CoolingPanel:RadiantConvective:Water':
                        zequip_name = str(ext_grp.getString(1))
                        if zequip_name in rad_pnl_names:
                            rad_pnl_dicts[zequip_name]['zone_hvac_equip_list'] = str(zhvac_equip_ls.getString(0))

            # get all the zonehvac equip connections and get the zone name 
            zhvac_equip_conns = workspace.getObjectsByType('ZoneHVAC:EquipmentConnections')
            for zhvac_equip_conn in zhvac_equip_conns:
                equip_ls_name = str(zhvac_equip_conn.getString(1))
                for rad_pnl_name in rad_pnl_names:
                    equip_ls_name_ref = rad_pnl_dicts[rad_pnl_name]['zone_hvac_equip_list']
                    if equip_ls_name == equip_ls_name_ref:
                        tzone_name = str(zhvac_equip_conn.getString(0))
                        rad_pnl_dicts[rad_pnl_name]['thermal_zone_name'] = tzone_name
                        break

            return rad_pnl_dicts

def run( self, workspace: openstudio.Workspace,
            runner: openstudio.measure.OSRunner,
            user_arguments: openstudio.measure.OSArgumentMap,):
            """Defines what happens when the measure is run."""
            super().run(workspace, runner, user_arguments)  # Do **NOT** remove this line

            if not (runner.validateUserArguments(self.arguments(workspace), user_arguments)):
                return False

            rad_pnls = workspace.getObjectsByType('ZoneHVAC:CoolingPanel:RadiantConvective:Water')
            # get which thermal zone the radiant panel 
            rad_pnl_dicts = get_tzone_of_rad_clg_pnls(rad_pnls, workspace, runner)
            # report initial condition of workspace
            runner.registerInitialCondition(f"The building has {len(rad_pnls)} rad_panels")
            # reverse translate the idf into osmod
            rev_translate = openstudio.energyplus.ReverseTranslator()
            osmod = rev_translate.translateWorkspace(workspace)
            # get all the thermal zones
            thermal_zones = osmod.getThermalZones()
            rad_pnl_names = rad_pnl_dicts.keys()
            for rad_pnl_name in rad_pnl_names:
                thermal_zone_name_ref = rad_pnl_dicts[rad_pnl_name]['thermal_zone_name']
                # get all the surfaces that is in this zone
                sel_tzone = None
                for thermal_zone in thermal_zones:
                    thermal_zone_name = thermal_zone.nameString()
                    if thermal_zone_name == thermal_zone_name_ref:
                        sel_tzone = thermal_zone
                        break
                tzone_surfaces = []
                tzone_spaces = sel_tzone.spaces()
                for tzone_space in tzone_spaces:
                    tzone_surfaces.extend(tzone_space.surfaces())

                # region: calculate all the surface areas of each surface type
                ttl_wall_area = 0
                ttl_flr_area = 0
                ttl_ceil_area = 0
                for tzone_srf in tzone_surfaces:
                    srf_type = str(tzone_srf.surfaceType())
                    srf_area = tzone_srf.grossArea()
                    if srf_type == 'Wall':
                        ttl_wall_area += srf_area
                    elif srf_type == 'Floor':
                        ttl_flr_area += srf_area
                    elif srf_type == 'RoofCeiling':
                        ttl_ceil_area += srf_area
                # endregion: calculate all the surface areas of each surface type

                frac_rad_on_ppl = rad_pnl_dicts[rad_pnl_name]['frac_rad_on_ppl']
                # Assume that 45% of what is not on people is on the walls
                frac_wall = (1.0 - frac_rad_on_ppl) * 0.45
                # Assume that 50% of what is not on people is on the floor
                frac_floor = (1.0 - frac_rad_on_ppl) * 0.5
                # Assume that 5% of what is not on people is on the walls
                frac_ceil = (1.0 - frac_rad_on_ppl) * 0.05

                rad_pnl_idf = rad_pnl_dicts[rad_pnl_name]['idf_obj']
                rad_pnl_idf.clearExtensibleGroups()
                ttl_frac = 0
                for scnt,tzone_srf in enumerate(tzone_surfaces):
                    new_grp = rad_pnl_idf.pushExtensibleGroup()
                    srf_name = tzone_srf.nameString()
                    srf_type = str(tzone_srf.surfaceType())
                    srf_area = tzone_srf.grossArea()
                    new_grp.setString(0, srf_name)
                    if srf_type == 'Wall':
                        frac_srf = srf_area/ttl_wall_area*frac_wall
                    elif srf_type == 'Floor':
                        frac_srf = srf_area/ttl_flr_area*frac_floor
                    elif srf_type == 'RoofCeiling':
                        frac_srf = srf_area/ttl_ceil_area*frac_ceil
                    ttl_frac+=frac_srf
                    new_grp.setDouble(1, frac_srf)

            runner.registerFinalCondition(f"The building finished with {len(rad_pnls)} zones.")
            return True
edit flag offensive delete link more
1

answered 2026-01-21 13:13:20 -0500

updated 2026-01-21 13:21:21 -0500

Seems entirely automated by OpenStudio (SDK), based on the following weighted area distribution (see here, Lines 170 to 190):

-  5% of radiant energy (not on people) hits floor surfaces
- 40% of radiant energy (not on people) hits ceiling surfaces
- 55% of radiant energy (not on people) hits wall surfaces

You can easily test this with the Example model that comes with the OpenStudio Application. Check the ZoneHVAC:CoolingPanel:RadiantConvective:Water object in the generated in.idf - a tally of surface type-specific area weights will match the above distribution.

Haven't tried, but one should be able to adjust these with an EnergyPlus Measure - or even by editing the generated IDF by hand.

edit flag offensive delete link more

Comments

1

Seems worth requesting these inputs as an enhancement at https://github.com/NREL/OpenStudio/is...

shorowit's avatar shorowit  ( 2026-01-21 14:50:02 -0500 )edit
1

@Denis Bourgeois Thanks, looking at the forward translator of openstudiosdk is a very good way to figure out what is available. The default is kind of weird considering radiant ceiling panels are on the ceiling, it is not reasonable that 40% of the radiant energy hits the ceiling surfaces. Definitely needs to do some adjustment and it seems like the only way to do this is to write a energyplus measure that adjust the generated idf file.

@shorowit ya definitely a good request for future radiant panels modeling.

Thanks both for answering the question I have a better idea for my next step

chenkianwee's avatar chenkianwee  ( 2026-01-21 16:25:25 -0500 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Training Workshops

Question Tools

1 follower

Stats

Asked: 2026-01-20 16:49:38 -0500

Seen: 265 times

Last updated: Mar 06