Skip to content

Commit

Permalink
fix(package): Fix a list few bugs identified though eQuest importing
Browse files Browse the repository at this point in the history
  • Loading branch information
chriswmackey committed Apr 27, 2024
1 parent 2dc0a05 commit 4f564d1
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 62 deletions.
6 changes: 6 additions & 0 deletions honeybee_doe2/construction.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ def opaque_construction_to_inp(construction):
it does NOT include the constituent MATERIAL definitions and their properties.
"""
doe2_id = clean_doe2_string(construction.identifier, RES_CHARS)
# if the construction has no heat capacity, simply make a U-VALUE construction
if construction.area_heat_capacity == 0:
con_cond = UValue().to_unit([construction.u_factor], 'Btu/h-ft2-F', 'W/m2-K')[0]
keywords = ('TYPE', 'U-VALUE')
values = ('U-VALUE', round(con_cond, 6))
return generate_inp_string(doe2_id, 'CONSTRUCTION', keywords, values)
# create the specification of material layers
layer_id = '{}_l'.format(doe2_id)
layers = ['"{}"'.format(clean_doe2_string(mat, RES_CHARS))
Expand Down
4 changes: 2 additions & 2 deletions honeybee_doe2/load.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@ def equipment_to_inp(room):
epd = EnergyFlux().to_unit([equip.watts_per_area], 'W/ft2', 'W/m2')[0]
epd = round(epd, 3)
eqp_sch = clean_doe2_string(equip.schedule.display_name, RES_CHARS)
eqp_sch = '"{}"'.format(eqp_sch)
eqp_sch = '("{}")'.format(eqp_sch)
sens_fract = 1 - equip.latent_fraction - equip.lost_fraction
equip_val = (epd, eqp_sch, sens_fract, equip.latent_fraction,
equip.radiant_fraction)

equip_kwd = ('EQUIPMENT-W/AREA', 'EQUIPMENT-SCHEDULE',
equip_kwd = ('EQUIPMENT-W/AREA', 'EQUIP-SCHEDULE',
'EQUIP-SENSIBLE', 'EQUIP-LATENT', 'EQUIP-RAD-FRAC')
return equip_kwd, equip_val

Expand Down
36 changes: 19 additions & 17 deletions honeybee_doe2/schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from honeybee.typing import clean_doe2_string

from .config import RES_CHARS
from .util import generate_inp_string
from .util import generate_inp_string, generate_inp_string_list_format


def schedule_type_limit_to_inp(type_limit):
Expand All @@ -33,9 +33,9 @@ def schedule_day_to_inp(day_schedule, type_limit=None):
# setup a function to format list of values correctly
def _format_day_values(values_to_format):
if len(values_to_format) == 1:
return'({})'.format(values_to_format[0])
return'({})'.format(round(values_to_format[0], 3))
else:
return str(tuple(values_to_format))
return str(tuple(round(v, 3) for v in values_to_format))

# loop through the hourly values and write them in the format DOE-2 likes
prev_count, prev_hour, prev_values = 0, 1, [hour_values[0]]
Expand Down Expand Up @@ -97,8 +97,10 @@ def schedule_ruleset_to_inp(schedule):
# setup the DOE-2 identifier and lists for keywords and values
doe2_id = clean_doe2_string(schedule.identifier, RES_CHARS)
type_text = schedule_type_limit_to_inp(schedule.schedule_type_limit)
day_types = ['(MON)', '(TUE)', '(WED)', '(THU)', '(FRI)', '(SAT)', '(SUN)',
'(HOL)', '(HDD)', '(CDD)']
day_types = [
'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday',
'Sunday', 'Holiday', 'Winter Design Day', 'Summer Design Day'
]

def _get_week_list(schedule, rule_indices):
"""Get a list of the ScheduleDay identifiers applied on each day of the week."""
Expand Down Expand Up @@ -149,13 +151,13 @@ def _inp_week_schedule_from_rule_indices(schedule, rule_indices, week_index):
# add extra days (including summer and winter design days)
week_fields.extend(_get_extra_week_fields(schedule))
week_keywords, week_values = ['TYPE'], [type_text]
day_list = []
for day_type, day_sch in zip(day_types, week_fields):
week_keywords.append('DAYS')
week_values.append(day_type)
week_keywords.append('DAY-SCHEDULES')
week_values.append('"{}"'.format(day_sch))
week_schedule = generate_inp_string(
week_sch_id, 'WEEK-SCHEDULE', week_keywords, week_values)
day_list.append('"{}", $ {}'.format(day_sch, day_type))
week_keywords.append('DAY-SCHEDULES')
week_values.append(day_list)
week_schedule = generate_inp_string_list_format(
week_sch_id, 'WEEK-SCHEDULE-PD', week_keywords, week_values)
return week_schedule, week_sch_id

def _inp_week_schedule_from_week_list(schedule, week_list, week_index):
Expand All @@ -167,13 +169,13 @@ def _inp_week_schedule_from_week_list(schedule, week_list, week_index):
week_fields.append(week_fields.pop(0)) # DOE-2 starts week on Monday; not Sunday
week_fields.extend(_get_extra_week_fields(schedule))
week_keywords, week_values = ['TYPE'], [type_text]
day_list = []
for day_type, day_sch in zip(day_types, week_fields):
week_keywords.append('DAYS')
week_values.append(day_type)
week_keywords.append('DAY-SCHEDULES')
week_values.append('"{}"'.format(day_sch))
week_schedule = generate_inp_string(
week_sch_id, 'WEEK-SCHEDULE', week_keywords, week_values)
day_list.append('"{}", $ {}'.format(day_sch, day_type))
week_keywords.append('DAY-SCHEDULES')
week_values.append(day_list)
week_schedule = generate_inp_string_list_format(
week_sch_id, 'WEEK-SCHEDULE-PD', week_keywords, week_values)
return week_schedule, week_sch_id

# prepare to create a full Schedule:Year
Expand Down
15 changes: 9 additions & 6 deletions honeybee_doe2/writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def face_3d_to_inp(face_3d, parent_name='HB object'):
ref_plane = Plane(face_3d.normal, llc_origin, proj_x)
vertices = [ref_plane.xyz_to_xy(pt) for pt in pts_3d]
else: # horizontal; ensure vertices are always counterclockwise from above
azimuth = 180
azimuth = 180.0
llc = Point2D(llc_origin.x, llc_origin.y)
vertices = [Point2D(v.x - llc.x, v.y - llc.y) for v in pts_3d]
if tilt > 180 - DOE2_ANGLE_TOL:
Expand Down Expand Up @@ -104,7 +104,6 @@ def shade_mesh_to_inp(shade_mesh):
"""
# TODO: Sense when the shade is a rectangle and, if so, translate it without POLYGON
# set up collector lists and properties for all shades
shade_type = 'FIXED-SHADE' if shade_mesh.is_detached else 'BUILDING-SHADE'
base_id = clean_doe2_string(shade_mesh.identifier, GEO_CHARS)
trans = energy_trans_sch_to_transmittance(shade_mesh)
keywords = ('SHAPE', 'POLYGON', 'TRANSMITTANCE',
Expand All @@ -120,7 +119,7 @@ def shade_mesh_to_inp(shade_mesh):
values = ('POLYGON', '"{} Plg"'.format(doe2_id), trans,
round(origin.x, GEO_DEC_COUNT), round(origin.y, GEO_DEC_COUNT),
round(origin.z, GEO_DEC_COUNT), tilt, az)
shade_def = generate_inp_string(doe2_id, shade_type, keywords, values)
shade_def = generate_inp_string(doe2_id, 'FIXED-SHADE', keywords, values)
shade_polygons.append(shade_polygon)
shade_defs.append(shade_def)
return shade_polygons, shade_defs
Expand All @@ -141,7 +140,6 @@ def shade_to_inp(shade):
"""
# TODO: Sense when the shade is a rectangle and, if so, translate it without POLYGON
# create the polygon string from the geometry
shade_type = 'FIXED-SHADE' if shade.is_detached else 'BUILDING-SHADE'
doe2_id = clean_doe2_string(shade.identifier, GEO_CHARS)
shd_geo = shade.geometry if shade.altitude > 0 else shade.geometry.flip()
clean_geo = shd_geo.remove_colinear_vertices(DOE2_TOLERANCE)
Expand All @@ -154,7 +152,7 @@ def shade_to_inp(shade):
values = ('POLYGON', '"{} Plg"'.format(doe2_id), trans,
round(origin.x, GEO_DEC_COUNT), round(origin.y, GEO_DEC_COUNT),
round(origin.z, GEO_DEC_COUNT), tilt, az)
shade_def = generate_inp_string(doe2_id, shade_type, keywords, values)
shade_def = generate_inp_string(doe2_id, 'FIXED-SHADE', keywords, values)
return shade_polygon, shade_def


Expand Down Expand Up @@ -200,7 +198,9 @@ def door_to_inp(door):

# create the aperture definition
doe2_id = clean_doe2_string(door.identifier, GEO_CHARS)
constr_o_name = door.properties.energy.construction.identifier
dr_con = door.properties.energy.construction
constr_o_name = dr_con.identifier if isinstance(dr_con, OpaqueConstruction) \
else dr_con.identifier + '_d'
constr = clean_doe2_string(constr_o_name, RES_CHARS)
keywords = ('X', 'Y', 'WIDTH', 'HEIGHT', 'CONSTRUCTION')
values = (round(min_2d.x, GEO_DEC_COUNT), round(min_2d.y, GEO_DEC_COUNT),
Expand Down Expand Up @@ -568,6 +568,9 @@ def model_to_inp(
model_str.append(window_construction_to_inp(w_con))
model_str.append(header_comment_minor('Door Construction'))
for dr_con in door_constructions:
if not isinstance(dr_con, OpaqueConstruction):
dr_con = dr_con.duplicate()
dr_con.identifier = dr_con.identifier + '_d'
model_str.append(door_construction_to_inp(dr_con))

# loop through rooms grouped by floor level and boundary to get polygons
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
honeybee-energy>=1.105.48
honeybee-energy>=1.105.50
12 changes: 6 additions & 6 deletions tests/construction_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def test_material_nomass_to_inp():
assert inp_str == \
'"Insulation R-2" = MATERIAL\n' \
' TYPE = RESISTANCE\n' \
' RESISTANCE = 11.357\n' \
' RESISTANCE = 11.356527\n' \
' ..\n'


Expand Down Expand Up @@ -89,31 +89,31 @@ def test_window_construction_to_inp():
'"NECB Window Construction" = GLASS-TYPE\n' \
' TYPE = SHADING-COEF\n' \
' SHADING-COEF = 0.46\n' \
' GLASS-CONDUCT = 0.302\n' \
' GLASS-CONDUCT = 0.302373\n' \
' ..\n'

inp_str = double_low_e.to_inp()
assert inp_str == \
'"Double Low-E Window" = GLASS-TYPE\n' \
' TYPE = SHADING-COEF\n' \
' SHADING-COEF = 0.488\n' \
' GLASS-CONDUCT = 0.299\n' \
' GLASS-CONDUCT = 0.299039\n' \
' ..\n'

inp_str = double_clear.to_inp()
assert inp_str == \
'"Double Clear Window" = GLASS-TYPE\n' \
' TYPE = SHADING-COEF\n' \
' SHADING-COEF = 0.791\n' \
' GLASS-CONDUCT = 0.479\n' \
' GLASS-CONDUCT = 0.479229\n' \
' ..\n'

inp_str = triple_clear.to_inp()
assert inp_str == \
'"Triple Clear Window" = GLASS-TYPE\n' \
' TYPE = SHADING-COEF\n' \
' SHADING-COEF = 0.688\n' \
' GLASS-CONDUCT = 0.309\n' \
' GLASS-CONDUCT = 0.309475\n' \
' ..\n'


Expand All @@ -139,7 +139,7 @@ def test_window_construction_shade_to_inp():
'"Double Low-E with Shade" = GLASS-TYPE\n' \
' TYPE = SHADING-COEF\n' \
' SHADING-COEF = 0.488\n' \
' GLASS-CONDUCT = 0.299\n' \
' GLASS-CONDUCT = 0.299039\n' \
' ..\n'


Expand Down
34 changes: 13 additions & 21 deletions tests/schedule_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,28 +155,20 @@ def test_schedule_ruleset_to_inp():
' ..\n'
assert len(inp_week_strs) == 1
assert inp_week_strs[0] == \
'"Office Occupancy Week 1" = WEEK-SCHEDULE\n' \
'"Office Occupancy Week 1" = WEEK-SCHEDULE-PD\n' \
' TYPE = FRACTION\n' \
' DAYS = (MON)\n' \
' DAY-SCHEDULES = "Weekday Office Occupancy"\n' \
' DAYS = (TUE)\n' \
' DAY-SCHEDULES = "Weekday Office Occupancy"\n' \
' DAYS = (WED)\n' \
' DAY-SCHEDULES = "Weekday Office Occupancy"\n' \
' DAYS = (THU)\n' \
' DAY-SCHEDULES = "Weekday Office Occupancy"\n' \
' DAYS = (FRI)\n' \
' DAY-SCHEDULES = "Weekday Office Occupancy"\n' \
' DAYS = (SAT)\n' \
' DAY-SCHEDULES = "Saturday Office Occupancy"\n' \
' DAYS = (SUN)\n' \
' DAY-SCHEDULES = "Sunday Office Occupancy"\n' \
' DAYS = (HOL)\n' \
' DAY-SCHEDULES = "Sunday Office Occupancy"\n' \
' DAYS = (HDD)\n' \
' DAY-SCHEDULES = "Winter Office Occupancy"\n' \
' DAYS = (CDD)\n' \
' DAY-SCHEDULES = "Summer Office Occupancy"\n' \
' DAY-SCHEDULES = (\n' \
' "Weekday Office Occupancy", $ Monday,\n' \
' "Weekday Office Occupancy", $ Tuesday,\n' \
' "Weekday Office Occupancy", $ Wednesday,\n' \
' "Weekday Office Occupancy", $ Thursday,\n' \
' "Weekday Office Occupancy", $ Friday,\n' \
' "Saturday Office Occupancy", $ Saturday,\n' \
' "Sunday Office Occupancy", $ Sunday,\n' \
' "Sunday Office Occupancy", $ Holiday,\n' \
' "Winter Office Occupancy", $ Winter Design Day,\n' \
' "Summer Office Occupancy", $ Summer Design Day,\n' \
' )\n' \
' ..\n'


Expand Down
18 changes: 9 additions & 9 deletions tests/writer_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,31 +30,31 @@ def test_shade_writer():
' V4 = (0.0, 1.0)\n' \
' ..\n'
assert shade_def == \
'"overhang" = BUILDING-SHADE\n' \
'"overhang" = FIXED-SHADE\n' \
' SHAPE = POLYGON\n' \
' POLYGON = "overhang Plg"\n' \
' TRANSMITTANCE = 0\n' \
' X-REF = 0.0\n' \
' Y-REF = 0.0\n' \
' Z-REF = 3.0\n' \
' TILT = 0.0\n' \
' AZIMUTH = 0.0\n' \
' AZIMUTH = 180.0\n' \
' ..\n'

fritted_glass_trans = ScheduleRuleset.from_constant_value(
'Fritted Glass', 0.5, schedule_types.fractional)
shade.properties.energy.transmittance_schedule = fritted_glass_trans
shade_polygon, shade_def = shade.to.inp(shade)
assert shade_def == \
'"overhang" = BUILDING-SHADE\n' \
'"overhang" = FIXED-SHADE\n' \
' SHAPE = POLYGON\n' \
' POLYGON = "overhang Plg"\n' \
' TRANSMITTANCE = 0.5\n' \
' X-REF = 0.0\n' \
' Y-REF = 0.0\n' \
' Z-REF = 3.0\n' \
' TILT = 0.0\n' \
' AZIMUTH = 0.0\n' \
' AZIMUTH = 180.0\n' \
' ..\n'


Expand Down Expand Up @@ -84,7 +84,7 @@ def test_shade_mesh_writer():
' Y-REF = 0.0\n' \
' Z-REF = 4.0\n' \
' TILT = 0.0\n' \
' AZIMUTH = 0.0\n' \
' AZIMUTH = 180.0\n' \
' ..\n'

fritted_glass_trans = ScheduleRuleset.from_constant_value(
Expand All @@ -100,7 +100,7 @@ def test_shade_mesh_writer():
' Y-REF = 0.0\n' \
' Z-REF = 4.0\n' \
' TILT = 0.0\n' \
' AZIMUTH = 0.0\n' \
' AZIMUTH = 180.0\n' \
' ..\n'


Expand Down Expand Up @@ -245,7 +245,7 @@ def test_face_writer():
' POLYGON = "roof face Plg"\n' \
' CONSTRUCTION = "Thick Concrete Construction"\n' \
' TILT = 0.0\n' \
' AZIMUTH = 0.0\n' \
' AZIMUTH = 180.0\n' \
' X = 0.0\n' \
' Y = 0.0\n' \
' Z = 3.0\n' \
Expand All @@ -266,7 +266,7 @@ def test_face_writer():
' POLYGON = "floor face Plg"\n' \
' CONSTRUCTION = "Thick Concrete Construction"\n' \
' TILT = 180.0\n' \
' AZIMUTH = 0.0\n' \
' AZIMUTH = 180.0\n' \
' X = 10.0\n' \
' Y = 0.0\n' \
' Z = 0.0\n' \
Expand Down Expand Up @@ -329,7 +329,7 @@ def test_room_writer():
' LIGHTING-SCHEDULE = "Generic Office Lighting"\n' \
' LIGHT-TO-RETURN = 0.0\n' \
' EQUIPMENT-W/AREA = 0.96\n' \
' EQUIPMENT-SCHEDULE = "Generic Office Equipment"\n' \
' EQUIP-SCHEDULE = ("Generic Office Equipment")\n' \
' EQUIP-SENSIBLE = 1.0\n' \
' EQUIP-LATENT = 0.0\n' \
' EQUIP-RAD-FRAC = 0.5\n' \
Expand Down

0 comments on commit 4f564d1

Please sign in to comment.