Keeping on with the automation trend, again with my workflow (maybe others also), I use Revit HVAC Zoning as a zonemap to know what spaces belong together for a thermal zone. This is the same zonemap I use for IESVE when having to move spaces to a zone and then combining the plenums (which is super slow).
The script from the plenum post used to autocreate the plenums, and somehow the zone parameter could be used to merge the plenums. Now the only thing is that when IESVE merges the plenums, it makes all the partitions that belong to the merged plenum and air boundary like in this example of 3 spaces in one zone
You would like the plenums of rooms within the same thermal zone to be merged together into a single plenum space with no partitions/air boundaries between them. Is that correct?
If that’s the case, this might be something that we automate differently than the other two since Pollination already has a concept of zoning, and we can add an option to the translation to merge the plenums for rooms on the same zone.
Let’s see what @chriswmackey thinks about this. I feel this is a common workflow and worth being an option in the standard export workflow.
Thanks again for post the automation requests! I’m very glad that you discovered this aspect of Pollination. It has been there for some time now, but we have been mostly using it for renaming rooms and moving models to the origin. These more advanced workflows make all the development worthwhile.
“You would like the plenums of rooms within the same thermal zone to be merged together into a single plenum space with no partitions/air boundaries between them. Is that correct?”
Yes, exactly. This ideally makes the plenum merging instantaneous rather than manually merging.
To second what @mostapha said, I think we can probably support an automated workflow for this at some point once we expose the “Zone” attribute of Rooms on the model editor UI. In the meantime, there is a way to get what you want in the Model Editor, which is a little manual but should be far quicker than using IESVE to manage the plenum geometry.
What you can do is that, after you have set up all of your plenum depths correctly, you can use Separate Plenums button at the top of the “Levels” table:
This will convert the plenum properties assigned to the rooms into real plenum rooms on their own plenum story, which you can see on the canvas of the model editor. From there, you can use the Merge Rooms command to merge the plenums together that are a part of the same zone. Then the plenum for each zone will be exported as a single room in the IESVE GEM.
Granted, we realize that this workflow is pretty manual and uni-directional. There isn’t an easy way to go back to a model with plenums assigned as attributes from the detailed plenum model. But, hopefully, this workflow can tide you over until we figure out how to expose (probably a few) options for how to merge zone geometry in the model editor. I think there are some people who want the option to merge all of the room geometry of the zone together into a single closed volume but I think we can support both this option and a “Merge Plenums Only” option.
from model_editor import Editor
editor = Editor()
model = editor.model
for room in model.room_2ds:
h = room.user_data.get('Space Ceiling Height', 0)
if h == 0:
continue
# divide the value by 12 assuming the input values are in inches
room.ceiling_plenum_depth = room.floor_to_ceiling_height - h
editor.update()
and then this to see how they where “grouped”
from model_editor import Editor
editor = Editor()
model = editor.model
# Step 1: Find all "Plenum" rooms and group them by Zone
zone_groups = {}
for room in model.room_2ds:
if "Plenum" in room.display_name:
zone = room.user_data.get("Zone")
if zone:
zone_groups.setdefault(zone, []).append(room)
# Step 2: Print results
print("🔎 Plenum rooms grouped by Zone:\n")
for zone, rooms in zone_groups.items():
print(f"🟦 Zone: {zone}")
for r in rooms:
print(f" - {r.display_name}")
print("")
print(f"âś… Found {sum(len(v) for v in zone_groups.values())} plenum rooms across {len(zone_groups)} zone(s).")
it was successful in telling me which rooms (plenums) shared the same zone data. i wonder if from here it could be taken to an “auto-merge” script?
i may not be using this right but wanted to confirm
from model_editor import Editor
editor = Editor()
model = editor.model
# Step 1: Group plenum rooms by 'Zone'. same as the previous grouping script.
zone_groups = {}
for room in model.room_2ds:
if "Plenum" in room.display_name:
zone = room.user_data.get("Zone")
if zone:
zone_groups.setdefault(zone, []).append(room)
# Step 1: Group plenum rooms by 'Zone'. same as the previous grouping script.
# Step 2: Join room_2ds per zone group======================================
joined_rooms = []
for zone, rooms in zone_groups.items():
if len(rooms) < 2:
continue # Nothing to merge
#static join_room_2ds(room_2ds, min_separation=0, tolerance=0.01, identifier=None)[source]
merged_room = join_room_2ds(
room_2ds=rooms,
min_separation=0,
tolerance=0.01,
identifier=None
)
print(f"Merge applied")
editor.update()
oh wait…would this still need to me to select the plenum rooms? right now I have been using this under the assumption i don’t have to select anything.
No, your script is written to run on the whole model. Not the selected rooms.
Your script is just creating the merged_room but is not replacing the rooms in the model with the new merged room. Now that I think about it, you should probably instead use this method to join the rooms of the same story together. That will edit the story object in place so that you do not need to go deleting and adding rooms from the model after they are joined.
Let me know if it’s clear or if you want me to just edit your script for you.
something i do notice when merging plenums even using the standard merge tool, is that the if there are plenums with different depths, it will merge as one room with a single depth/offset vs one room with the depth offset
Sorry that this fell through the cracks just an hour after I said that I could help. Here is a version of your script, which should update the model in-place:
from model_editor import Editor
editor = Editor()
model = editor.model
for story in model.stories:
# Step 1: Group plenums by 'Zone' (same as previous grouping script)
zone_groups = {}
for room in story.room_2ds:
if "Plenum" in room.display_name:
zone = room.user_data.get("Zone")
if zone:
zone_groups.setdefault(zone, []).append(room.identifier)
# Step 2: Join room_2ds per zone group
for zone, room_ids in zone_groups.items():
if len(room_ids) < 2:
continue # Nothing to merge
story.join_room_2ds(room_ids, model.tolerance)
print(f"Merge applied")
editor.update()
That should do the trick.
Yea, there’s not really a good way to represent this with explicit plenum Room2Ds on the Model Editor canvas. Each dragonfly Room2D can have only one planar floor_geometry so a change in floor height within the same Room2D cannot be represented.
We will keep this case in mind when we eventually add options for merging zones when going from Dragonfly (2D schema) to Honeybee (3D schema). As a fully-detailed 3D schema, Honeybee would have no problem representing changes in floor heights like that. So you’ll be able to represent this case in the future.
For the time being, do you think you can work around it by just using consistent plenum depths for all of the plenums in each zone? Or do you want some code that you can put in your script to ensure that all of the plenums have the same floor height before you merge them?
Some code that you can put in the script to ensure that all of the plenums have the same floor height before merging might be useful. This could at ideally take care of 50%+ in the model editor vs IESVE (which takes so long)