EPlus Model (idf file)¶
An EnergyPlus Model (Epm) is a python object describing a building model (idf or epjson file). This object contains tables, which contain records.
Epm¶
Perform imports, and prepare EPlus base directory path (to work with example files).
import os
import opyplus as op
eplus_dir_path = op.get_eplus_base_dir_path((9, 0, 1))
Load Epm
# prepare path
idf_path = os.path.join(
eplus_dir_path,
"ExampleFiles",
"1ZoneEvapCooler.idf"
)
# load epm
epm = op.Epm.load(idf_path)
print(epm)
Epm
AirLoopHVAC: 1 record
AirLoopHVAC:ControllerList: 1 record
AirLoopHVAC:OutdoorAirSystem: 1 record
AirLoopHVAC:OutdoorAirSystem:EquipmentList: 1 record
AirLoopHVAC:ReturnPath: 1 record
AirLoopHVAC:SupplyPath: 1 record
AirLoopHVAC:ZoneMixer: 1 record
AirLoopHVAC:ZoneSplitter: 1 record
AirTerminal:SingleDuct:Uncontrolled: 1 record
AvailabilityManager:HighTemperatureTurnOn: 1 record
AvailabilityManager:LowTemperatureTurnOff: 1 record
AvailabilityManagerAssignmentList: 1 record
Branch: 1 record
BranchList: 1 record
Building: 1 record
BuildingSurface:Detailed: 6 records
Construction: 3 records
Controller:OutdoorAir: 1 record
EvaporativeCooler:Direct:CelDekPad: 1 record
Fan:ConstantVolume: 1 record
GlobalGeometryRules: 1 record
HeatBalanceAlgorithm: 1 record
Material: 1 record
Material:NoMass: 2 records
OutdoorAir:Mixer: 1 record
OutdoorAir:Node: 1 record
Output:Constructions: 1 record
Output:Meter:MeterFileOnly: 4 records
Output:Surfaces:Drawing: 1 record
Output:Table:SummaryReports: 1 record
Output:Variable: 8 records
Output:VariableDictionary: 1 record
OutputControl:Table:Style: 1 record
RunPeriod: 1 record
Schedule:Compact: 4 records
ScheduleTypeLimits: 2 records
SimulationControl: 1 record
Site:GroundTemperature:BuildingSurface: 1 record
Site:Location: 1 record
SizingPeriod:DesignDay: 2 records
SurfaceConvectionAlgorithm:Inside: 1 record
SurfaceConvectionAlgorithm:Outside: 1 record
ThermostatSetpoint:SingleHeating: 1 record
Timestep: 1 record
Version: 1 record
Zone: 1 record
ZoneControl:Thermostat: 1 record
ZoneHVAC:Baseboard:Convective:Electric: 1 record
ZoneHVAC:EquipmentConnections: 1 record
ZoneHVAC:EquipmentList: 1 record
ZoneInfiltration:DesignFlowRate: 1 record
Save Epm in a new file
epm.save("my_idf.idf")
Table¶
A table is a collection of records of the same type.
Retrieve and explore the zone table.
zones = epm.Zone
print(zones)
print(f"\nzones: {len(zones)}\n")
for z in zones:
print(z.name)
Table Zone (Zone)
main zone
zones: 1
main zone
Queryset¶
A queryset is the result of a select query on a table.
# or a table
qs = epm.Zone.select(lambda x: x.name == "main zone")
# or another queryset
qs = qs.select(lambda x: x.name == "main zone")
print("records: ", qs)
print("\niter:")
for r in qs:
print(r["name"])
print("\nget item:")
print(qs[0])
records: <Queryset of Zone: 1 records>
iter:
main zone
get item:
Zone,
main zone, ! Name
0.0, ! Direction of Relative North
0.0, ! X Origin
0.0, ! Y Origin
0.0, ! Z Origin
1, ! Type
1, ! Multiplier
autocalculate, ! Ceiling Height
autocalculate; ! Volume
Records¶
Get record¶
# from a table
building = epm.Building.one(lambda x: x.name == "Bldg")
# or from queryset
building = epm.Building.select(lambda x: x["name"] == "Bldg").one()
Add record¶
# add from a table
new_sch = epm.Schedule_Compact.add(
name="Heating Setpoint Schedule - new[1]",
schedule_type_limits_name="Any Number",
field_1="Through: 12/31",
field_2="For: AllDays",
field_3="Until: 24:00,20.0"
)
print("found: ", epm.Schedule_Compact.one(lambda x: x.name == "heating setpoint schedule - new[1]") is new_sch)
# may also add extensible fields in afterwards add from table (only for extensible records)
new_sch = epm.Schedule_Compact.add(
name="Heating Setpoint Schedule - new[2]",
schedule_type_limits_name="Any Number"
)
new_sch.add_fields(
"Through: 12/31",
"For: AllDays",
"Until: 24:00,20.0"
)
found: True
Remove record¶
new_sch.delete()
print("found: ", len(epm.Schedule_Compact.select(lambda x: x.name == "heating setpoint schedule - new[2]")) == 1)
found: False
Batch add (and remove)¶
schedules = [
dict(
name="Heating Setpoint Schedule - 0",
schedule_type_limits_name="Any Number",
field_1="Through: 12/31",
field_2="For: AllDays",
field_3="Until: 24:00,20.0"
),
dict(
name="Heating Setpoint Schedule - 1",
schedule_type_limits_name="Any Number",
field_1="Through: 12/31",
field_2="For: AllDays",
field_3="Until: 24:00,20.0"
),
dict(
name="Heating Setpoint Schedule - 2",
schedule_type_limits_name="Any Number",
field_1="Through: 12/31",
field_2="For: AllDays",
field_3="Until: 24:00,20.0"
),
]
# idf syntax
added = epm.Schedule_Compact.batch_add(schedules)
print("added:")
for a in added:
print(a["name"])
added.delete()
added:
heating setpoint schedule - 0
heating setpoint schedule - 1
heating setpoint schedule - 2
Display info¶
print(building.get_info())
print("")
print(building)
Building (Building)
0: Name (name)
* default: NONE
* retaincase:
1: North Axis (north_axis)
* default: 0.0
* note: degrees from true North
* type: real
* units: deg
2: Terrain (terrain)
* default: Suburbs
* key: Country; Suburbs; City; Ocean; Urban
* note: Country=FlatOpenCountry | Suburbs=CountryTownsSuburbs | City=CityCenter | Ocean=body of water (5km) | Urban=Urban-Industrial-Forest
* type: choice
3: Loads Convergence Tolerance Value (loads_convergence_tolerance_value)
* default: .04
* maximum: .5
* minimum>: 0.0
* note: Loads Convergence Tolerance Value is a fraction of load
* type: real
4: Temperature Convergence Tolerance Value (temperature_convergence_tolerance_value)
* default: .4
* maximum: .5
* minimum>: 0.0
* type: real
* units: deltaC
5: Solar Distribution (solar_distribution)
* default: FullExterior
* key: MinimalShadowing; FullExterior; FullInteriorAndExterior; FullExteriorWithReflections; FullInteriorAndExteriorWithReflections
* note: MinimalShadowing | FullExterior | FullInteriorAndExterior | FullExteriorWithReflections | FullInteriorAndExteriorWithReflections
* type: choice
6: Maximum Number of Warmup Days (maximum_number_of_warmup_days)
* default: 25
* minimum>: 0
* note: EnergyPlus will only use as many warmup days as needed to reach convergence tolerance.; This field's value should NOT be set less than 25.
* type: integer
7: Minimum Number of Warmup Days (minimum_number_of_warmup_days)
* default: 6
* minimum>: 0
* note: The minimum number of warmup days that produce enough temperature and flux history; to start EnergyPlus simulation for all reference buildings was suggested to be 6.; When this field is greater than the maximum warmup days defined previous field; the maximum number of warmup days will be reset to the minimum value entered here.; Warmup days will be set to be the value you entered when it is less than the default 6.
* type: integer
Building,
Bldg, ! Name
0.0, ! North Axis
suburbs, ! Terrain
0.05, ! Loads Convergence Tolerance Value
0.05, ! Temperature Convergence Tolerance Value
minimalshadowing, ! Solar Distribution
30, ! Maximum Number of Warmup Days
6; ! Minimum Number of Warmup Days
Get field value¶
print("name: ", building.name)
print("name: ", building["name"])
print("name: ", building[0])
name: Bldg
name: Bldg
name: Bldg
Set basic field¶
old_name = building.terrain
print(f"old name: {old_name}")
building.terrain = "Downtown"
print(f"new name: {building.terrain}")
building.terrain = old_name
old name: suburbs
new name: downtown
Replace basic fields¶
sch = epm.Schedule_Compact.one(lambda x: x.name == "heating setpoint schedule")
sch.name = "Heating Setpoint Schedule"
sch.field_1 = "Through: 12/31"
sch[3] = "For: AllDays" # index syntax
print(sch)
sch.name = "Heating Setpoint Schedule new_name"
print(sch)
Schedule:Compact,
heating setpoint schedule, ! Name
any number, ! Schedule Type Limits Name
through: 12/31, ! Field 1
for: alldays, ! Field 2
until: 24:00, ! Field 3
20.0; ! Field 4
Schedule:Compact,
heating setpoint schedule new_name, ! Name
any number, ! Schedule Type Limits Name
through: 12/31, ! Field 1
for: alldays, ! Field 2
until: 24:00, ! Field 3
20.0; ! Field 4
Set record fields¶
# work with setpoint record
setpoint = epm.ThermostatSetpoint_SingleHeating.one(lambda x: x.name == "heating setpoint")
print(setpoint)
# can set directly by name
setpoint.setpoint_temperature_schedule_name = "zone control type sched"
print(setpoint)
# or set record
new_sch = epm.Schedule_Compact.one(lambda x: x["name"] == "heating setpoint schedule new_name")
setpoint.setpoint_temperature_schedule_name = new_sch
print(setpoint)
# reset old value
setpoint.setpoint_temperature_schedule_name = sch
ThermostatSetpoint:SingleHeating,
heating setpoint, ! Name
heating setpoint schedule new_name; ! Setpoint Temperature Schedule Name
ThermostatSetpoint:SingleHeating,
heating setpoint, ! Name
zone control type sched; ! Setpoint Temperature Schedule Name
ThermostatSetpoint:SingleHeating,
heating setpoint, ! Name
heating setpoint schedule new_name; ! Setpoint Temperature Schedule Name
Add fields (only for extensibles)¶
sch.add_fields(
"Until: 24:00",
"25"
)
print(sch)
Schedule:Compact,
heating setpoint schedule new_name, ! Name
any number, ! Schedule Type Limits Name
through: 12/31, ! Field 1
for: alldays, ! Field 2
until: 24:00, ! Field 3
20.0, ! Field 4
until: 24:00, ! Field 5
25; ! Field 6
Explore links¶
pointing = sch.get_pointing_records()
print("pointing on sch:")
for _pointing in sch.get_pointing_records():
print(_pointing)
# todo: [GL] explore by table
setpoint = pointing.ThermostatSetpoint_SingleHeating[0]
print("pointed by setpoint:")
for _pointed in setpoint.get_pointed_records():
print(_pointed)
# todo: [GL] explore by table
pointing on sch:
thermostatsetpoint_singleheating
pointed by setpoint:
schedule_compact
Case sensitivity¶
Table names¶
Table refs have a case, but getitem on idf is case insensitive
print("tables:")
print(epm.Zone)
print(epm.zOnE)
tables:
Table Zone (Zone)
main zone
Table Zone (Zone)
main zone
Record field keys¶
Record field keys are lower case with underscores instead of spaces
# todo: put an example with spaces
print("\nbuilding name:")
print(building.name)
print(building["name"])
building name:
Bldg
Bldg
Record field values¶
In Energy Plus, some record field values retain case (are case sensitive) and others don’t
print(building.get_info())
# => building name retains case, terrain doesn't
Building (Building)
0: Name (name)
* default: NONE
* retaincase:
1: North Axis (north_axis)
* default: 0.0
* note: degrees from true North
* type: real
* units: deg
2: Terrain (terrain)
* default: Suburbs
* key: Country; Suburbs; City; Ocean; Urban
* note: Country=FlatOpenCountry | Suburbs=CountryTownsSuburbs | City=CityCenter | Ocean=body of water (5km) | Urban=Urban-Industrial-Forest
* type: choice
3: Loads Convergence Tolerance Value (loads_convergence_tolerance_value)
* default: .04
* maximum: .5
* minimum>: 0.0
* note: Loads Convergence Tolerance Value is a fraction of load
* type: real
4: Temperature Convergence Tolerance Value (temperature_convergence_tolerance_value)
* default: .4
* maximum: .5
* minimum>: 0.0
* type: real
* units: deltaC
5: Solar Distribution (solar_distribution)
* default: FullExterior
* key: MinimalShadowing; FullExterior; FullInteriorAndExterior; FullExteriorWithReflections; FullInteriorAndExteriorWithReflections
* note: MinimalShadowing | FullExterior | FullInteriorAndExterior | FullExteriorWithReflections | FullInteriorAndExteriorWithReflections
* type: choice
6: Maximum Number of Warmup Days (maximum_number_of_warmup_days)
* default: 25
* minimum>: 0
* note: EnergyPlus will only use as many warmup days as needed to reach convergence tolerance.; This field's value should NOT be set less than 25.
* type: integer
7: Minimum Number of Warmup Days (minimum_number_of_warmup_days)
* default: 6
* minimum>: 0
* note: The minimum number of warmup days that produce enough temperature and flux history; to start EnergyPlus simulation for all reference buildings was suggested to be 6.; When this field is greater than the maximum warmup days defined previous field; the maximum number of warmup days will be reset to the minimum value entered here.; Warmup days will be set to be the value you entered when it is less than the default 6.
* type: integer
Note
Field values that don’t retain case are always forced to lowercase. Field values that retain case keep their case sensitive value.
building.name = "StaysCamelCase"
building.terrain = "Suburbs" # will be set to lowercase
print(building)
Building,
StaysCamelCase, ! Name
0.0, ! North Axis
suburbs, ! Terrain
0.05, ! Loads Convergence Tolerance Value
0.05, ! Temperature Convergence Tolerance Value
minimalshadowing, ! Solar Distribution
30, ! Maximum Number of Warmup Days
6; ! Minimum Number of Warmup Days
Note
Don’t forget these rules when filtering
print("retains, case not respected:", len(epm.Building.select(lambda x: x.name == "stayscamelcase"))) # not ok
print("retains, case respected:", len(epm.Building.select(lambda x: x.name == "StaysCamelCase"))) # ok
print("doesn't retain, uppercase: ", len(epm.Building.select(lambda x: x.terrain == "Suburbs"))) # not ok
print("doesn't retain, lowercase: ", len(epm.Building.select(lambda x: x.terrain == "suburbs"))) # ok
retains, case not respected: 0
retains, case respected: 1
doesn't retain, uppercase: 0
doesn't retain, lowercase: 1