Two-step EnergyPlus simulation

Dear all,

What is the most straightforward way to conduct a 2-step simulation in EP via Honeybee?

As shown in this (very interesting) study, when ground data is unavailable, a cost-effective way to calibrate the slab/ground heat transfer is to consider the average indoor temperatures of all thermal zones -1.5°C as input for the monthly ground temperature via the Site:GroundTemperature:BuildingSurface object.

As such, I’m currently running a first simulation with default ground temperature (18ºC), manually extracting the average indoor temperatures, and inputing them (-1.5°C) as monthly ground temperatures using _add_string to run the second simulation. However, I’d like to automate this process as I intend to apply an evolutionary optimization to my workflow.

1 Like

So I’ve not done it with LBT before buuuut: you *should possibly (I’ve not done this myself before) be able to use _add_string to add “GroundHeatTransfer:Slab” object and “GroundHeatTransfer:Control” and E+ should automatically call the slab preprocessor.

I’m not sure if that is explicitly going to do what you want? but I know that’s a thing that automates ground heat transfer :sweat_smile:

Otherwise you could probs copy off E+ EMS average zone air temp example , use that output as input data for a ghpy component that’s going to create what your currently manually inputting into the _add_string.

That’s all I can really think of at the moment!

1 Like

Hey Trevor! Thanks a lot for the useful tips :mage:

About the slab preprocessor, I was a little skeptic about using it since I would have to set basically all other objects to default (ALBEDO:Surface Albedo:No Snow, HIN:Indoor HConv:Upward, and so on), since I’m simulating various cities with no soil data. That’s why I’m betting all my chips on the 2-step approach (average indoor temperature as input to ground temperature).

However, how exactly would you automate this input to output step in HB? Would you transform one ModelToOSM’s output through a ghpy component and connect it as input to another ModelToOSM component? Sorry if those are silly questions, it seems a bit confusing to me.

1 Like

AHHH, did not know that about the slab pre-proc!

Yeah no worries! making an example of a way you could go about it; may be easier than trying to explain; though I think EMS might be the best means; rather than doing “two-step sims”, should be able to “get the previous timestep zone temp, do math, set ground temp, do next timestep”.

this works: though depending on how big your MOO study and model is; reading the sql results out could be add second+ to each sim, so maybe doing custom outputs for csv data and straight up turning off the sql output for the first sim; might speed it up a hair? (52.2 KB)


Perfect!! Thank you again for the support, Trevor. This will definitely do for now, but I’ll try EMS as well later on.

1 Like

No problem!
Happy could be helpful!

1 Like

I just wanted to say that I think @TrevorFedyna 's solution is the best way to solve this.

If you really wanted to try using the EMS, the easiest way to do it is probably using the OpenStudio SDK inside a GHPython component to edit the OSM like you see here. However, for a case like this, I’d be worried that you get some positive feedback loops that result in extreme or unrealistic ground temperatures, especially for unconditioned spaces. You could imagine a scenario where the temperature in the Room drops, so then the temperature of the ground drops, causing the temperature in the room to drop further, and so on…


@TrevorFedyna, I just realized your example isn’t considering the weighted average temperature based on room floor areas (and that’s fine because your model is single-zoned). So, to account for multiple zones scenarios, I tweaked your code a bit:

from ladybug_rhino.grasshopper import all_required_inputs
from honeybee_energy.result.match import match_rooms_to_data

if all_required_inputs(ghenv.Component):
    # Create matched lists of rooms temperatures and areas
    matched_tuples = match_rooms_to_data(_air_temp, _rooms)
    rooms_temperatures = [tup[1].values for tup in matched_tuples]
    rooms_areas = [tup[0].floor_area for tup in matched_tuples]
    # Multiply each temperature by its room area and sum it for all 
    # rooms in each month
    m_temps = [0 for _ in range(12)]
    for i, room_temps in enumerate(rooms_temperatures):
        for month, temp in enumerate(room_temps):
            m_temps[month] += temp*rooms_areas[i]
    # Calculate weighted average and write IDF string
    weighted_temps = [round(v/sum(rooms_areas),1) - 1.5 for v in m_temps]
    clean_weighted_temps = (",".join(str(v) for v in weighted_temps))
    idf_str_ = "Site:GroundTemperature:BuildingSurface,{};".format(clean_weighted_temps) (55.9 KB)

1 Like

Awesome!! you write much cleaner and more readable code than I do :sweat_smile:

1 Like

Haha I would not understand it myself were it not for some exhaustive comments along the code

1 Like

I wish I had the forethought and patients to do the same :sweat_smile: bad habbit of over-abreviating things and forgetting docstrings and comments; then when i get back to some code I wrote in the past I’m all: :thinking:

1 Like