This example extends Example 3 by adding a constraint to ensure that CIBSE TM52 summertime comfort criteria are met - in addition to the "Minimise % PPD Discomfort" optimisation objective. DesignBuilder doesn't include a built-in KPI for TM52 comfort so this is added through a Python script.
The application of 2 custom KPIs is demonstrated, one for the PPD discomfort objective and the other for the TM52 constraint.
Open the model saved from Example 3 and open the Model options dialog. On the Simulation tab, under the Outputs header, check the CIBSE TM52 checkbox to ensure that DesignBuilder generates standard TM52 outputs. These standard outputs will need further processing to create a single discomfort value for the whole building and we'll write a Python script to do that in Step 3.
1. Open the Parametric, Optimisation and UA/SA Analysis Settings dialog by clicking on the toolbar icon.
2. Go to the Constraints tab and add 1 new constraint for TM52 discomfort. The steps involved are described below.
To create the TM52 comfort constraint, a new Summary Output (aka KPI) must first be created. Click on the Output KPI to open the list of existing Summary Outputs in the Info panel. Our new custom KPI won't be listed there at first, so create it now by clicking on the existing Custom Script Summary Output on the list of KPIs, click on the Create copy of highlighted item Info toolbar icon and edit the clone. Make the following settings on the Summary Output dialog.
Note: The "TM52 Discomfort %" name entered here on the Summary Outputs dialog must match the name given in the custom KPI script described below. You may like to copy the name and paste it somewhere safe where you can easily access it later when writing the script.
Save the newly created KPI and select it on the Optimisation Constraints dialog.
Set the maximum value to 1 so the dialog should look as follows:
The next task is to write the script that will read the base TM52 simulation outputs from the SQL output file, process them and pass back to DesignBuilder as a Custom KPI. Steps are as follows.
1. Click on the Scripts toolbar icon to open the Script Manager dialog and click on the Enable scripts checkbox.
2. Click on the Script browse item. A list of the existing scripts appears in the Info panel to the right.
3. Click on the Python-Script category and press the Add new item Info toolbar icon to open the Edit script dialog.
4. Check the Enable program option.
5. Name the script "TM52 Discomfort".
6. Copy and paste the script below into the script window.
The script reads the TM52 Criteria 1, 2, and 3 outputs and checks against the corresponding criteria based on TM52 rules. Any zone passing the overall annual TM52 criteria has it's area excluded from the total area failing. The TM52 Discomfort % value for the simulation is then added to the special "ParamResultsTmp" table together with the name of the Objective to be picked up by DesignBuilder when it processes the simulation results.
The 2 Summary outputs, "TM52 Discomfort %" and "PPD Discomfort > 20%" are each added as separate records to the "ParamResultsTmp" table. More KPIs could be added to the table in a more sophisticated analysis.
"""
Use CIBSE TM52 results as optimisation KPI.
Required model inputs:
- Enable TM52 outputs
- Add a "Custom Script" KPI, use "TM52 Discomfort %" name
- Run a "Standard" simulation to make sure that TM52 outputs are present
The script calculates a percentage of failing TM52 relevant zones.
"""
import ctypes
import os
from db_eplusout_reader import Variable, get_results
from db_eplusout_reader.constants import *
from db_eplusout_reader.exceptions import NoResults
threshold_crit1 = 3
threshold_crit2 = 6
threshold_crit3 = 0
def show_message(title, text):
ctypes.windll.user32.MessageBoxW(0, text, title, 0)
def zone_fails_tm52(zone_name):
"""Verify if given zone meets tm52 criteria."""
outputs_path = os.path.join(api_environment.EnergyPlusFolder, "eplusout.sql")
variable1 = Variable(RP, "EMS", "CIBSE TM52 Criterion 1 {}".format(zone_name), "%")
variable2 = Variable(D, "EMS", "CIBSE TM52 Criterion 2 {}".format(zone_name), "C")
variable3 = Variable(RP, "EMS", "CIBSE TM52 Criterion 3 {}".format(zone_name), "hr")
criterion_1_results = get_results(outputs_path, variable1)
criterion_2_results = get_results(outputs_path, variable2)
criterion_3_results = get_results(outputs_path, variable3)
criterion_1 = criterion_1_results.scalar
crit2_series = criterion_2_results.first_array
criterion_2 = max(crit2_series)
criterion_3 = criterion_3_results.scalar
counter = 0
if criterion_1 > threshold_crit1:
counter += 1
if criterion_2 > threshold_crit2:
counter += 1
if criterion_3 > threshold_crit3:
counter += 1
return counter >= 2
def after_energy_simulation():
site = api_environment.Site
fail_area = 0
total_area = 0 # area only includes TM52 zones
for block in active_building.BuildingBlocks:
for zone in block.Zones:
zone_name = zone.GetAttribute("SSEPObjectNameInOP")
try:
if zone_fails_tm52(zone_name):
fail_area += zone.FloorArea
total_area += zone.FloorArea
except NoResults:
pass
try:
percentage_area_fail = (fail_area / total_area) * 100
except ZeroDivisionError:
raise NoResults("No TM52 results found!")
# show_message("Results TM52", "{}% fails, total_area {}m2, fail_area: {}m2".format(percentage_area_fail, total_area, fail_area))
table = site.GetTable("ParamResultsTmp")
record = table.AddRecord()
record[0] = "TM52 Discomfort %"
record[1] = str(percentage_area_fail)
Tip: To save time you can copy the above script and paste it into the dialog.
Click on the Simulation tab and press update to re-run a base annual simulation with the Monthly and RunPeriod results option checked.
Important Note: Make sure to switch off Daily, Hourly and Sub-hourly results for this simulation to ensure that the upcoming optimisation simulations and results processing are done efficiently.
Note: The script above is shown with the show_message line commented out, but the message can be enabled by removing the "#" character to display TM52 compliance results. Once you are confident that the TM52 script is working well you can delete or comment out the show_message line to avoid seeing messages after each simulation during the optimisation.
Navigate to the Optimisation + UA/SA tab on the Simulation screen and press the Update toolbar icon to open the Optimisation Calculation Options dialog. You can accept the default optimisation settings.
Press the Start button to run the optimisation simulations.
Tip: When running constrained optimisations it is usually necessary to test more iterations to find optimal solutions that meet the combined requirements of the objectives and the constraint(s). This is because while the fitness of designs is partly assessed based on whether constraints are satisfied or not, a stronger driver for the selection of new generations is the fitness based on the objectives.
After the optimisation has converged and you have closed the Calculation Options dialog, you should see results similar to those below on the main screen.
The results show that in order to simultaneously minimise both PPD discomfort and heating load while also passing the requirements of TM52, the optimal settings are:
Heating setpoint temperature close to 20°C.
Natural ventilation setpoint temperatures close to 25.5°C. Natural ventilation setpoints below this cause increased simultaneous heating and venting and hence increase heating load for no benefit in comfort, while setpoints above this range do not provide sufficient venting in the summer to meet the TM52 constraint.
Window opening % of 100% are required to meet the TM52 constraint. Values below this do not give enough venting to keep occupants cool in summer and pass TM52 summer discomfort requirements.
Comparing these results with equivalent results from Example 3 without the TM52 constraint, we can see that the need to pass TM52 requires additional natural ventilation, both in terms of the natural ventilation setpoint temperature and window opening area. While 50% window opening area and a 26-27°C natural ventilation setpoint is enough to keep most of the building comfortable most of the time based on PPD alone, adding the "pass TM52 constraint" requires much more ventilation, which in turn involves more simultaneous heating and venting during swing seasons and so heating load is significantly higher.
A more sophisticated set of system control rules would need to be introduced to avoid the simultaneous heating and venting that is occurring in the "optimal" solutions listed above, allowing the heating load to be reduced while still passing TM52. For example adding controls to limit the window % opening area based on the outside and inside temperatures would help reduce simultaneous heating and venting. EMS code could be added to achieve this.