From 250f09fee9e1bce64a093c765f01c187efee162f Mon Sep 17 00:00:00 2001 From: Michel Date: Tue, 18 Apr 2017 10:33:58 -0400 Subject: [PATCH 01/20] Packaging EnergyPlus simulation code using oplus --- bpeng/simulation/__init__.py | 1 + bpeng/simulation/base.py | 813 ++++++ bpeng/simulation/building_hvac_oplus.py | 214 ++ bpeng/simulation/design_days.py | 200 ++ bpeng/simulation/geometry.py | 184 ++ bpeng/simulation/initial_idf/empty_start.idf | 2653 ++++++++++++++++++ bpeng/simulation/midrise.py | 763 +++++ requirements.txt | 2 + tests/simulation/__init__.py | 0 tests/simulation/test_midrise_idf.py | 9 + 10 files changed, 4839 insertions(+) create mode 100644 bpeng/simulation/__init__.py create mode 100644 bpeng/simulation/base.py create mode 100644 bpeng/simulation/building_hvac_oplus.py create mode 100644 bpeng/simulation/design_days.py create mode 100644 bpeng/simulation/geometry.py create mode 100644 bpeng/simulation/initial_idf/empty_start.idf create mode 100644 bpeng/simulation/midrise.py create mode 100644 tests/simulation/__init__.py create mode 100644 tests/simulation/test_midrise_idf.py diff --git a/bpeng/simulation/__init__.py b/bpeng/simulation/__init__.py new file mode 100644 index 0000000..4e5b92e --- /dev/null +++ b/bpeng/simulation/__init__.py @@ -0,0 +1 @@ +from .midrise import MidRiseApart diff --git a/bpeng/simulation/base.py b/bpeng/simulation/base.py new file mode 100644 index 0000000..0530631 --- /dev/null +++ b/bpeng/simulation/base.py @@ -0,0 +1,813 @@ +import abc +import math +import datetime +from .geometry import (coord_to_meters, tuple_convert_float, fix_degenerate_surface, + walls_vertex, floor_vertex, ceiling_vertex, offset_center_ratio) +from oplus import IDF +from .design_days import add_dday +from .building_hvac_oplus import * + + +class BaseSim: + __metaclass__ = abc.ABCMeta + + # Default EnergyPlus objects + bsd_new = """BuildingSurface:Detailed, + , ! - Name + , ! - Surface Type + , ! - Construction Name + , ! - Zone Name + , ! - Outside Boundary Condition + , ! - Outside Boundary Condition Object + , ! - Sun Exposure + , ! - Wind Exposure + , ! - View Factor to Ground + , ! - Number of Vertices""" + + zone_new = """Zone, + , ! - Name""" + + fsd_new = """FenestrationSurface:Detailed, + , ! Name + , ! Surface Type + , ! Construction Name + , ! Building Surface Name + , ! Outside Boundary Condition Object + , ! View Factor to Ground + , ! Shading Control Name + , ! Frame and Divider Name + , ! Multiplier + , ! Number of Vertices""" + + shading_new = """Shading:Building:Detailed, + , !- Name + , !- Transmittance Schedule Name + , !- Number of Vertices""" + + zonelist_new = """ZoneList, + , ! - Name""" + + zoneinfil_ACH_new = """ZoneInfiltration:DesignFlowRate, + , !- Name + , !- Zone or ZoneList Name + , !- Schedule Name + AirChanges/Hour, !- Design Flow Rate Calculation Method + , !- Design Flow Rate {m3/s} + , !- Flow per Zone Floor Area {m3/s-m2} + , !- Flow per Exterior Surface Area {m3/s-m2} + , !- Air Changes per Hour {1/hr} + , !- Constant Term Coefficient + , !- Temperature Term Coefficient + , !- Velocity Term Coefficient + ; !- Velocity Squared Term Coefficient""" + + # Functions using oplus IDFObjects and IDF classes to add the geometry of the building envelope to and IDF + # file, given the coordinates, construction, zone, and boundary conditions of a surface. + + def __init__(self, idf_start_file=None): + if idf_start_file is None: + idf_source = IDF('initial_idf/empty_start.idf') + else: + idf_source = IDF(idf_start_file) + + self.idf = idf_source.copy() + + def bsd_add(self, name, cons_name, zone_name, obc, sun_exp, w_exp, nb_v, coords, surface_type=None, obc_obj=None): + """ + Add a BuildingSurface:Detailed IDF object to a given IDF file and arguments. For more detailed information + about BuildingSurface:Detailed object, see EnergyPlus Documentation, InputOutputReference.pdf + Parameters + ---------- + idf: Oplus IDF object + name: str + Name of the surface + cons_name: Oplus IDFObject + Corresponding to the IDF object Construction, which indicates the composition of the surface + zone_name: Oplus IDFObject + IDF object referring to the zone which the surface belongs to + obc: str + For details about what this string should be, see InputOutputReference.pdf. Refer the outside boundary + condition type of the surface. + sun_exp: str + Whether or not the surface is exposed to sun. Must be "NoSun" or "SunExposed". + w_exp: str + Whether or not the surface is exposed to wind. Must be "NoWind" or "WindExposed". + nb_v: int + Number of vertices of the surface. + coords: list of tuples + List of tuples (x,y,z) for the coordinates of the vertices. The order of the list must be consistent + with the IDF object GlobalGeometryRules. For more details see InputOutputReference.pdf. + surface_type: str (optional but recommended) + Type of the surface. For valid types, see InputOutputReference.pdf. + obc_obj: Oplus IDFObject (optional) + If the obc (outside boundary condition) refers to another surface (or IDF object) this field must not be + None, but must contain the IDF object corresponding to this object. For example, if two zones are separated + by a wall, then the outside boundary condition will be "Surface", and the outside boundary condition object + would be the object of the other surface in the adjacent zone. For more details, + see InputOutputReference.pdf + + Returns + ------- + s1: Oplus IDFObject + BuildingSurface:Detailed + """ + nb_xyz = len(coords) + if nb_v != nb_xyz: + raise ValueError("""Length mismatch: Expected axis has {nb_v} elements, + new values have {nb_xyz} elements""".format(nb_v=nb_v, nb_xyz=nb_xyz)) + + s1 = self.idf.add_object(bsd_new) + s1["name"] = name + s1["surface type"] = surface_type + s1["construction name"] = cons_name + s1["zone name"] = zone_name + s1["outside boundary condition"] = obc + s1["outside boundary condition object"] = obc_obj + s1["sun exposure"] = sun_exp + s1["wind exposure"] = w_exp + s1["number of vertices"] = nb_v + i = 1 + for x, y, z in coords: + s1.add_field(x, "Vertex %i X-coordinate" % i) + s1.add_field(y, "Vertex %i Y-coordinate" % i) + s1.add_field(z, "Vertex %i Z-coordinate" % i) + i += 1 + + return s1 + + def zone_add(self, zone_name): + """ + Add a zone IDF object + Parameters + ---------- + idf: Oplus IDF object + zone_name: str + Name of the zone + Returns + ------- + z: Zone Oplus IDFObject + """ + z = self.idf.add_object(zone_new) + z["name"] = zone_name + return z + + def extwindow_wall_ratio_add(self, cons_obj, surface_type="Window", window_to_wall_ratio=0.3, list_bsd=None, + obc_obj=None, multiplier=1, view_factor_to_ground="autocalculate", frame_divider=None, + shading_control=None): + """ + Add a Sub surface to a building surface (or a list of it). + Parameters + ---------- + idf: Oplus IDF object + cons_obj: Oplus IDFObject + Corresponding to the IDF object Construction, which indicates the composition of the surface + surface_type: str + Type of the surface. For valid types, see InputOutputReference.pdf. + window_to_wall_ratio: float + Between 0 and 1. + list_bsd: list + List containing all the BuildingSurface:Detailed Oplus IDFObjects to which the FenestrationSurface:Detailed + Oplus IDFObject has to be added. + obc_obj: Oplus IDFObject (optional) + Acoording to the field of the base surface, Outside Boundary Condition, this field must also be specified + or be left blank for the subsurface. For more details, see InputOutputReference.pdf + multiplier: int + Number of subsurfaces on the base surface. For more details, see InputOutputReference.pdf. + view_factor_to_ground: float or str + Float between 0 and 1. Can be "autocalculate" based on the tilt of the subsurface. + frame_divider: IDFObject (optional) + For more details, see InputOutputReference.pdf. + shading_control: IDFObject (optional) + For more details, see InputOutputReference.pdf. + + Returns + ------- + s: FenestrationSurface:Detailed Oplus IDFObject + """ + if list_bsd is None: + list_bsd = self.idf("buildingsurface:detailed").filter("outside boundary condition", "Outdoors") + + for bsd in list_bsd: + # Property assignment + s = self.idf.add_object(fsd_new) + s["name"] = "Sub Surface " + bsd["name"] + s["surface type"] = surface_type + s["construction name"] = cons_obj + s["building surface name"] = bsd + s["outside boundary condition object"] = obc_obj + s["view factor to ground"] = view_factor_to_ground + s["shading control name"] = shading_control + s["frame and divider name"] = frame_divider + s["multiplier"] = multiplier + n = bsd["number of vertices"] + s["number of vertices"] = bsd["number of vertices"] + + # Calculating new coordinates + bsd_vertices = bsd[-n * 3:] + coords = [(bsd_vertices[i * 3], bsd_vertices[i * 3 + 1], bsd_vertices[i * 3 + 2]) for i in range(n)] + new_coords = offset_center_ratio(window_to_wall_ratio, coords) + + # Adding window coordinates + i = 1 + for x, y, z in new_coords: + s.add_field(x, "Vertex %i X-coordinate" % i) + s.add_field(y, "Vertex %i Y-coordinate" % i) + s.add_field(z, "Vertex %i Z-coordinate" % i) + i += 1 + + def sbd_add(self, name, coords, nb_v=None, transmittance_schedule_name=None): + """ + Add a Shading:Building:Detailed IDF object to a given IDF file and arguments. For more detailed information + about Shading:Building:Detailed object, see EnergyPlus Documentation, InputOutputReference.pdf + Parameters + ---------- + idf: Oplus IDF object + name: str + Name of the shading surface + coords: list of tuples + List of tuples (x,y,z) for the coordinates of the vertices. The order of the list must be consistent + with the IDF object GlobalGeometryRules. For more details see InputOutputReference.pdf. + nb_v: int (optional but recommended) + Number of vertices of the surface. + transmittance_schedule_name: transmittance schedule name (optional) + The name of a schedule of solar transmittance values from 0.0 to 1.0 for the shading surface. If + a blank is entered in this field, the transmittance value defaults to 0.0, i.e., the shading surface is + opaque at all times. This scheduling can be used to allow for seasonal transmittance change, such + as for deciduous trees that have a higher transmittance in winter than in summer. + For more details, see InputOutputReference.pdf + + Returns + ------- + s1: Oplus IDFObject + Shading:Building:Detailed + """ + s1 = self.idf.add_object(shading_new) + s1["name"] = name + s1["transmittance schedule name"] = transmittance_schedule_name + s1["number of vertices"] = nb_v + i = 1 + for x, y, z in coords: + s1.add_field(x, "Vertex %i X-coordinate" % i) + s1.add_field(y, "Vertex %i Y-coordinate" % i) + s1.add_field(z, "Vertex %i Z-coordinate" % i) + i += 1 + return s1 + + def zinf_ach_add(self, name, zone_name, schedule_name, ACH, const_term_coef=None, + temp_term_coef=None, vel_term_coef=None, vel_sq_term_coef=None): + """ + Add a ZoneInfiltration:DesignFlowRate IDF object based on ACH value (Air Change per Hour) to a given + IDF file and arguments. For more detailed information about ZoneInfiltration:DesignFlowRate object, + see EnergyPlus Documentation, InputOutputReference.pdf + Parameters + ---------- + idf: Oplus IDF object + name: str + Name of the zone infiltration object + zone_name: str + Name of the zone or zone list obect to which it will attach the particular infiltration statement + schedule_name: str + Name of infiltration schedule + ACH: float + Air Change per Hour value, unit is in 1/hour + const_term_coef: float + Constant Term Coefficient, assumed None as default + see EnergyPlus Documentation InputOutputReference.pdf for more details + temp_term_coef: float + Temperature Term Coefficient, assumed None as default + see EnergyPlus Documentation InputOutputReference.pdf for more details + vel_term_coef: float + Velocity Term Coefficient, assumed None as default + see EnergyPlus Documentation InputOutputReference.pdf for more details + vel_sq_term_coef: float + Velocity Squared Term Coefficient, assumed None as default + see EnergyPlus Documentation InputOutputReference.pdf for more details + + Returns + ------- + zf1: Oplus IDFObject + ZoneInfiltration:DesignFlowRate + """ + zf1 = self.idf.add_object(zoneinfil_ACH_new) + zf1["name"] = name + zf1["zone or zonelist name"] = zone_name + zf1["schedule name"] = schedule_name + zf1["Air Changes per Hour {1/hr}"] = ACH + zf1["Constant Term Coefficient"] = const_term_coef + zf1["Constant Term Coefficient"] = temp_term_coef + zf1["Constant Term Coefficient"] = vel_term_coef + zf1["Constant Term Coefficient"] = vel_sq_term_coef + return zf1 + + def zonelist_all_add(self, name): + """ + Add zonelist IDF objects based on total number of zones. Oplus can ony add 100 zones per zonelist object + This function creates a zonelist object for each 100 zone objects + + Parameters + ---------- + idf: Oplus IDF object + name: str + Name assigned to zonelist + + Returns + ------- + zonelist_list: list + List of zonelist Oplus IDFObjects + """ + zones = idf("zone") + zonelist_number = 0 + for d in zones: + zonelist_number+=1 + zonelist_number /= 100 + zonelist_number = math.ceil(zonelist_number) # number of zonelists + zonelist_list = [] + for z in list(range(1, zonelist_number+1)): + zl = self.idf.add_object(zonelist_new) + zl["name"] = name + str(z) + i = 1 + for d in zones: + if (z-1)*100 < i <= z*100: + zl.add_field(d, comment="Zone Name %i" % i) + i += 1 + else: + i += 1 + zonelist_list.append(zl) + + return zonelist_list + + def idf_creation(self, building_name, building_shapefile, add_shading_analysis=False, building_shading_shapefile=None, + window_to_wall_ratio=0.16, infiltration_value='Automatic', add_people=False, people_value='Automatic', add_equipment=False, + equipment_value='Automatic', add_light=False, light_value='Automatic'): + """ + Create EnergyPlus input IDF file from building shapefile + Parameters + ---------- + building_name: str + building name or address + idf_start_file: str or os.path + path to idf emty starting file + file name + building_shapefile: pandas.DataFrame + building shapefile pandas DataFrame, Building Identification Number (BIN) in DataFrame index + add_shading_analysis: boolean + add surrounding building for shading analysis if True, default is False + building_shading_shapefile: pandas.DataFrame + surrounding buildings shapefile in pandas DataFrame + default is None, must add shading building shapefile if add_shading_analysis is True + Building Identification Number (BIN) in DataFrame index + window_to_wall_ratio: float + default value for multi-family buildings 16% + infiltration_value: float + default is 'Automatic' based on building construction year, see function zinf_year_add() in inherited class + if a float is inputted, it must be an Air Change per Hour value [1/hour], see function zinf_ach_add() in base class + add_people: boolean + add people internal gain components if True, default is False + people_value: float + occupancy value [person/m2] + default is 'Automatic' based on ASHRAE 189.1-2009 - MidriseApartment - Apartment - CZ4-8 from Open Studio + see object_input_database.py, variable name: 'people_apartment_new' + add_equipment: boolean + add equipment internal gain components if True, default is False + equipment_value: float + Watts per Zone Floor Area [W/m2] + default is 'Automatic' based on Residential building + see object_input_database.py, variable name: 'elecequip_apartment_new' + add_light: boolean + add light internal gain components if True, default is False + light_value: float + Watts per Zone Floor Area [W/m2] + default is 'Automatic' based on Residential building + see object_input_database.py, variable name: 'lights_apartment_new' + Returns + ------- + idf: Oplus idf object + """ + bldg_name = building_name + # idf_save_name = idf_save_name + + # IDF creation + start1 = time.clock() + print("Starting {} IDF creation.".format(bldg_name)) + + # Load shapefile data + build_shp = building_shapefile + + # Extract geometry Points + geom_div_col = build_shp['geometry'].apply(lambda st: st[st.find("(")+2:st.find(")")]).str.split(', ', expand=True) + geom_div_col.index = list(build_shp['bin']) + + # Meter Conversion + long_m, lat_m = coord_to_meters() + for column in geom_div_col.columns: + geom_div_col[column] = geom_div_col[column].apply(lambda x: tuple_convert_float(x, long_m, lat_m)) + + # Remove points that will create denegerate surfaces + geom_div_col = fix_degenerate_surface(geom_div_col) + + # Convert heighroof to meters + build_shp["heightroof"] *= 0.3048 + # Convert number of stories to height in meters* (1 floor = 10ft) + # *for shapefiles without "heightroof" column + # build_shp["heightroof"] = build_shp["stories"]*10*0.3048 + + # Database for walls, roof and ceilings + # Set origin to 0 + x0, y0 = geom_div_col.iloc[0,0] + + geom_origin = geom_div_col.copy() + for i in range(len(geom_origin.index)): + for j in range(len(geom_origin.columns)): + if geom_origin.iloc[i, j] is not None: + lst = list(geom_origin.iloc[i, j]) + lst[0] -= x0 + lst[1] -= y0 + geom_origin.iloc[i, j] = tuple(lst) + + build_shp_ep = build_shp.merge(geom_origin, left_on='bin', right_index=True) + build_shp_ep.index = list(build_shp_ep["bin"]) + + # Create list of (x,y,z) coordinates for each floor height for floors, roofs, and walls. + # These coordinates will be processed when adding the wall floors and roofs to the IDF file. + + walls = [] + floor = [] + ceiling = [] + num_floor = [] + index = [] + year = [] + for bin_ in geom_div_col.index: + input_ = geom_origin.ix[bin_] + h = build_shp_ep.ix[bin_]["heightroof"] + num_floor_tmp = build_shp_ep.ix[bin_]["num_floors"] + year_tmp = build_shp_ep.ix[bin_]["cnstrct_yr"] + h_l = list(np.linspace(0, h, num=(num_floor_tmp + 1))) + for i in range(len(h_l) - 1): + index.append(str(bin_) + " floor" + str(i + 1)) + hl = h_l[i] # lower height, or floor height, for a given floor + hh = h_l[i+1] # higher height, or ceiling height, for a given floor + num_floor.append(int(num_floor_tmp)) + walls.append(walls_vertex(input_, hl, hh)) + ceiling.append(ceiling_vertex(input_, hh)) + floor.append(floor_vertex(input_, hl)) + year.append(int(year_tmp)) + + input_ep_all = pd.DataFrame() + input_ep_all["walls"] = walls + input_ep_all["floor"] = floor + input_ep_all["roof"] = ceiling + input_ep_all["num_floor"] = num_floor + input_ep_all["year"] = year + input_ep_all.index = index + + ####################################################################### + # Adding buildings for shading analysis + if add_shading_analysis == True: + assert building_shading_shapefile == None, 'No shading building shapefile.' + + # Load shading building shapefile + shade_shp = building_shading_shapefile + + # Delete buildings with duplicated BIN number in shading building list + # dupbin = [1000000.0, 2000000.0, 3000000.0, 4000000.0, 5000000.0] + # for b in dupbin: + # shade_shp = shade_shp[shade_shp.bin != b] + + # Extract geometry Points + shade_geom_div_col = shade_shp['geometry'].apply(lambda st: st[st.find("(")+2:st.find(")")]).str.split(', ', expand=True) + shade_geom_div_col.index = list(shade_shp['bin']) + + # Meter Conversion + for column in shade_geom_div_col.columns: + shade_geom_div_col[column] = shade_geom_div_col[column].apply(lambda x: tuple_convert_float(x, long_m, lat_m)) + + # Convert heightroof to meters + shade_shp["heightroof"] *= 0.3048 + # Convert number of stories in surrounding buildings to height in meters (1 floor = 10ft) + # shade_shp["heightroof"] = shade_shp["stories"]*15*0.3048 + + # Remove points that will create denegerate surfaces + shade_geom_div_col = fix_degenerate_surface(shade_geom_div_col) + + # Database for walls, roof and ceilings + shade_origin = shade_geom_div_col.copy() + for i in range(len(shade_origin.index)): + for j in range(len(shade_origin.columns)): + if shade_origin.iloc[i, j] is not None: + lst = list(shade_origin.iloc[i, j]) + lst[0] -= x0 + lst[1] -= y0 + shade_origin.iloc[i, j] = tuple(lst) + + shade_shp_ep = shade_shp.merge(shade_origin, left_on='bin', right_index=True) + shade_shp_ep.index = list(shade_shp_ep["bin"]) + + # Create list of (x,y,z) coordinates for floors, roofs, and walls of shading buildings. + # These coordinates will be processed when adding the Shading:Building:Detailed to the IDF file. + + walls = [] + floor = [] + ceiling = [] + index = [] + for bin_ in shade_geom_div_col.index: + input_ = shade_origin.ix[bin_] + h = shade_shp_ep.ix[bin_]["heightroof"] + h_l = list(np.linspace(0, h, num=2)) + index.append(str(bin_)) + hl = h_l[0] # lower height, or floor height, for a given floor + hh = h_l[1] # higher height, or ceiling height, for a given floor + walls.append(walls_vertex(input_, hl, hh)) + ceiling.append(ceiling_vertex(input_, hh)) + floor.append(floor_vertex(input_, hl)) + + input_shade_ep_all = pd.DataFrame() + input_shade_ep_all["walls"] = walls + input_shade_ep_all["floor"] = floor + input_shade_ep_all["roof"] = ceiling + input_shade_ep_all.index = index + + ####################################################################### + # Create IDF + # idf_source = IDF(idf_start_file) + + # idf = idf_source.copy() + # self.idf.save_as(os.path.join(idf_save_path, idf_save_name + ".idf")) + + # Setting the Solar Distribution Field in Building objects. This value determines how EnergyPlus + # treats beam solar radiation and reflectances from exterior surfaces that strike the building and, + # ultimately, enter the zone. There are five choices: MinimalShadowing, FullExterior and + # FullInteriorAndExterior, FullExteriorWithReflections, FullInteriorAndExteriorWithReflections. + # See EnergyPlus InputOutputReference documentation for more information + for i in self.idf("Building"): + i['Solar Distribution'] = "FullExterior" + + # BuildingSurface:Detailed, FenestrationSurface:Detailed and Zones + # One window object is added per wall with outdoor outside boundary condition + # One zone is added per floor and per building. + input_ep = input_ep_all.copy() + + zone_list = [] + # cons_list = [] + num_floor_l = list(input_ep["num_floor"]) + year_l = list(input_ep["year"]) + for bin_, num_floor, year in zip(input_ep.index, num_floor_l, year_l): + + cons = cons_components(idf, year) + cons_wall = cons[0] + cons_groundfloor = cons[1] + cons_intfloor = cons[2] + cons_intceiling = cons[3] + cons_roof = cons[4] + cons_window = cons[5] + # cons_list.append(cons) + + new_bdg = False + if bin_.find("floor1") != -1: + floor_name = "Ground Floor " + str(bin_) + obc_floor = "Ground" + obc_obj_floor = None + cons_floor = cons_groundfloor + new_bdg = True + else: + floor_name = "Interior Floor " + str(bin_) + cons_floor = cons_intfloor + + if bin_.find("floor" + str(num_floor)) != -1: + ceiling_name = "Roof " + str(bin_) + surface_type_roof = "Roof" + cons_ceiling = cons_roof + else: + ceiling_name = "Interior Ceiling " + str(bin_) + surface_type_roof = "Ceiling" + cons_ceiling = cons_intceiling + + base_wall_name = "Wall " + str(bin_) + zone_name = "Zone " + str(bin_) + zone = zone_add(idf, zone_name=zone_name) + zone_list.append(zone) + w_l = input_ep.ix[bin_]["walls"] + f = input_ep.ix[bin_]["floor"] + r = input_ep.ix[bin_]["roof"] + + # Walls and Window + i = 1 + for w in w_l: + bsd_add(idf, base_wall_name + " " + str(i), cons_wall, zone, obc="Outdoors", obc_obj=None, + sun_exp="SunExposed", w_exp="WindExposed", nb_v=4, coords=w, surface_type="Wall") + lst_bsd = list(idf("buildingsurface:detailed").filter("name", base_wall_name + " " + str(i))) + extwindow_wall_ratio_add(idf, cons_window, surface_type="Window", window_to_wall_ratio=window_to_wall_ratio, list_bsd=lst_bsd) + i += 1 + + # Ground Floor and Roof underneath + nb_v_f = len(f) + floor_tmp = bsd_add(idf, floor_name, surface_type="Floor", cons_name=cons_floor, zone_name=zone, + obc=obc_floor, obc_obj=obc_obj_floor, sun_exp="NoSun", w_exp="NoWind", nb_v=nb_v_f, coords=f) + if not new_bdg: + roof_tmp["outside boundary condition"] = "Surface" + roof_tmp["outside boundary condition object"] = floor_tmp + roof_tmp["sun exposure"] = "NoSun" + roof_tmp["wind exposure"] = "NoWind" + + # Roof of the zone + nb_v_r = len(r) + roof_tmp = bsd_add(idf, ceiling_name, surface_type=surface_type_roof, cons_name=cons_ceiling, zone_name=zone, + obc="Outdoors", obc_obj=None, sun_exp="SunExposed", w_exp="WindExposed", nb_v=nb_v_r, coords=r) + + # Next floor outside boundary conditions + obc_floor = "Surface" + obc_obj_floor = roof_tmp + + input_ep['zone'] = zone_list + # input_ep['cons'] = cons_list + + # Create schedule Oplus IDFObjects + sch_inf_o = sch_infil_add(idf, 'MidriseApartment') + if add_people == True: + sch_occ_o = sch_occ_add(idf, 'MidriseApartment') + sch_act_o = sch_act_add(idf, 'MidriseApartment') + if add_equipment == True: + sch_equip_o = sch_equip_add(idf, 'MidriseApartment') + if add_light == True: + sch_light_o = sch_light_add(idf, 'MidriseApartment') + + # Create a zonelist Oplus IFDObject for each multifamily archetype + # Create zone infiltration/people/electric equipment/lighting Oplus IDFObjects for each zonelist + + zoneinf_list = [] + prevyear_list = [] + previous = 0 + count = 1 + thisyear = datetime.datetime.now().year + for y in [2004, 2009, thisyear]: + bdg_list = input_ep[(input_ep['year'] >= previous) & (input_ep['year'] < y)] + zonelist_number = len(bdg_list) + if zonelist_number == 0: + continue + zonelist_number /= 100 + zonelist_number = math.ceil(zonelist_number) # number of zonelists + zonelist_list = [] + for z in list(range(1, zonelist_number+1)): + zl = self.idf.add_object(zonelist_new) + zl["name"] = "Zonelist " + str(count) + i = 1 + for d in bdg_list["zone"]: + if (z-1)*100 < i <= z*100: + zl.add_field(d, comment="Zone Name %i" % i) + i += 1 + else: + i += 1 + zi = zinf_year_add(idf, str(count), zl, sch_inf_o, previous) + people_o = people_add(idf, 'MidriseApartment'+str(count), zl, sch_occ_o, sch_act_o) + equip_o = equip_add(idf, 'MidriseApartment'+str(count), zl, sch_equip_o) + lights_o = lights_add(idf, 'MidriseApartment'+str(count), zl, sch_light_o) + count += 1 + previous = y + + # Shading:Building:Detailed + if add_shading_analysis == True: + assert building_shading_shapefile != None, 'No shading building shapefile.' + input_shade_ep = input_shade_ep_all.copy() + + for bin_ in input_shade_ep.index: + w_l = input_shade_ep.ix[bin_]["walls"] + f = input_shade_ep.ix[bin_]["floor"] + r = input_shade_ep.ix[bin_]["roof"] + base_shading_surf_name = str(bin_) + " Shading Surface" + # Walls + i = 1 + for w in w_l: + sbd_add(idf, base_shading_surf_name + " Wall " + str(i), coords=w, nb_v=4, transmittance_schedule_name=None) + i += 1 + # Roofs + nb_v_r = len(r) + roof_tmp = sbd_add(idf, base_shading_surf_name + " Roof", coords=r, nb_v=nb_v_r, transmittance_schedule_name=None) + + # Save completed IDF file + # self.idf.save_as(os.path.join(idf_save_path, idf_save_name + ".idf")) + + # Add objects needed for simulation + # SimulationControl + sc = idf("SimulationControl").one + + for i in range(5): + sc[i] = "Yes" + + # RunPeriod + rp = idf("RunPeriod").one + + rp["end month"] = 12 + rp["end day of month"] = 31 + rp["day of week for start day"] = "Sunday" + + # Algorithm + conv = self.idf.add_object("ConvergenceLimits, 1;") + heat_balance = self.idf.add_object("""HeatBalanceAlgorithm, ConductionTransferFunction, 200;""") + shadow = self.idf.add_object("ShadowCalculation, AverageOverDaysInFrequency, 20, 15000;") + surface_conv_in = self.idf.add_object("SurfaceConvectionAlgorithm:Inside, TARP;") + surface_conv_out = self.idf.add_object("SurfaceConvectionAlgorithm:Outside, DOE-2;") + timestep = self.idf.add_object("Timestep, 1;") + zone_contaminant = self.idf.add_object("ZoneAirContaminantBalance, No;") + zone_heat_balance = self.idf.add_object("ZoneAirHeatBalanceAlgorithm, ThirdOrderBackwardDifference;") + + # Design Days + add_dday(self.idf) + + # HVAC + start = time.clock() + + print('Creating ZoneHVAC:IdealLoadsAirSystem objects to idf file') + + zone_eq_name = "ZoneHVAC:IdealLoadsAirSystem" + temperature_sch_type = add_sch_typelimits(idf, "Temperature", None, None, "Continuous", "temperature") + heating_sch = add_sch_compact(idf, "Heating Schedule", 21, sch_type_limit=temperature_sch_type) + cooling_sch = add_sch_compact(idf, "Cooling Schedule", 21, sch_type_limit=temperature_sch_type) + sch_controltype_setpoints = add_sch_typelimits(idf, "Setpoints", 0, 4, numeric_type="DISCRETE") + sch_on = idf("Schedule:Constant").filter("name", "Always On Discrete").one + for zone in idf("zone"): + base_name = zone["name"] + node_inlet = zone["name"] + " Supply Inlet Node" + name_tmp = zone["name"] + " Ideal Loads System" + air_dist_name = zone["name"] + "Thermal Zone Design Spec Zone Air Dist" + sz = add_sizing_zone(idf, zone) + ds_airdistrib = add_designspec_airdist(idf, air_dist_name) + zone_ilas_tmp = add_zone_ideal_airloads(idf, name_tmp, sch_on, node_inlet, + designspec_airdist=ds_airdistrib) + th_dual = add_thermostat_dual_setpoints(idf, base_name + " Thermostat Dual Setpoint", + heating_sch, cooling_sch) + sch_setpoints = add_sch_constant(idf, base_name + " Control Type Sch", 4, + sch_type_limit=sch_controltype_setpoints) + zone_control = add_zone_thermostat(idf, base_name + " Zone Thermostat", zone, sch_setpoints, th_dual) + eqlist = add_zone_equipmentlist(idf, base_name + " Thermal Zone Equipment", zone_eq_type=zone_eq_name, + zone_eq=zone_ilas_tmp["name"], cool_seq=1, heat_seq=1) + eqconnect = add_zone_equipmentconnection(idf, zone, base_name + " Zone Air Node Name", + base_name + " Zone Return Outlet", zone_eqlist=eqlist, + zone_inlet_node=node_inlet) + + print("Time to add ZoneHVAC:IdealLoadsAirSystem IDFObject: {} minutes for {} number of zones.".format((time.clock() - start)/60, len(idf("zone")))) + + # print(self.idf("ZoneHVAC:IdealLoadsAirSystem")[0].info()) + + self.idf.add_object("Output:VariableDictionary,IDF;") + # self.idf.add_object("Output:Variable,, Site Indoor Air Drybulb Temperature,hourly;") + # self.idf.add_object("Output:Variable,*,Zone Operative Temperature,hourly; !- Zone Average [C];") + self.idf.add_object("Output:Variable,*,Zone Ideal Loads Zone Total Cooling Energy,hourly; !- HVAC Sum [J]") + self.idf.add_object("Output:Variable,*,Zone Ideal Loads Zone Total Heating Energy,hourly; !- HVAC Sum [J]") + self.idf.add_object("Output:Variable,*,Zone Ideal Loads Zone Total Cooling Rate,hourly; !- HVAC Average [W]") + self.idf.add_object("Output:Variable,*,Zone Ideal Loads Zone Total Heating Rate,hourly; !- HVAC Average [W]") + # self.idf.add_object("Output:Variable,*,Zone Windows Total Heat Gain Energy,hourly; !- Zone Sum [J]") + # self.idf.add_object("Output:Variable,*,Zone Windows Total Heat Loss Energy,hourly; !- Zone Sum [J]") + # self.idf.add_object("Output:Variable,*,Zone Windows Total Heat Gain Rate,hourly; !- Zone Average [W]") + # self.idf.add_object("Output:Variable,*,Zone Windows Total Heat Loss Rate,hourly; !- Zone Average [W]") + # self.idf.add_object("Output:Variable,*,Zone Infiltration Total Heat Loss Energy,hourly; !- HVAC Sum [J]") + # self.idf.add_object("Output:Variable,*,Zone Infiltration Total Heat Gain Energy,hourly; !- HVAC Sum [J]") + # self.idf.add_object("Output:Variable,*,Zone Windows Total Transmitted Solar Radiation Energy,hourly; !- Zone Sum [J]") + # self.idf.add_object("Output:Variable,*,Site Daylighting Model Sky Clearness,hourly; !- Zone Average []") + # self.idf.add_object("Output:Variable,*,Surface Outside Face Sunlit Fraction,hourly; !- Zone Average []") + + # Save IDf file ready for simulation + # path_save = os.path.join(idf_save_path, idf_save_name + "_readysim.idf") + # self.idf.save_as(path_save) + + print("Time taken to create IDF for {}: {}".format(bldg_name, (time.clock() - start1)/60)) + + return self.idf + + + @abc.abstractmethod + def sch_infil_add(): + """Add infiltration schedule idf object for zone infiltration idf object.""" + + @abc.abstractmethod + def sch_occ_add(): + """Add occupancy schedule idf object for people idf object.""" + + @abc.abstractmethod + def sch_act_add(): + """Add activity schedule idf object for people idf object.""" + + @abc.abstractmethod + def sch_equip_add(): + """Add electric equipment schedule idf object for equipment idf object.""" + + @abc.abstractmethod + def sch_light_add(): + """Add light schedule idf object for lights idf object.""" + + @abc.abstractmethod + def zinf_year_add(): + """Add zone infiltration idf object.""" + + @abc.abstractmethod + def people_add(): + """Add people idf object for internal gains modeling.""" + + @abc.abstractmethod + def equip_add(): + """Add electric equipment idf object for internal gains modeling.""" + + @abc.abstractmethod + def lights_add(): + """Add lights idf object for internal gains modeling.""" + + @abc.abstractmethod + def cons_components(): + """Returns the construction list.""" diff --git a/bpeng/simulation/building_hvac_oplus.py b/bpeng/simulation/building_hvac_oplus.py new file mode 100644 index 0000000..68b45b5 --- /dev/null +++ b/bpeng/simulation/building_hvac_oplus.py @@ -0,0 +1,214 @@ +""" +Add the IDF objects for modeling a ZoneHVAC:IdealAirLoadsSystem for each zone (equipment, connections, schedules...). + +author: Thomas +""" + +# Default IDF objects to modify. Filled with default values or None. + +zone_thermostat_default = """ZoneControl:Thermostat, + name_to_change, !- Name + , !- Zone Name + , !- Control Type Schedule Name + , !- Control 1 Object Type + ; !- Control 1 Name""" + +sch_constant_default = """Schedule:Constant, + name_to_change, ! - Name + , ! - Schedule Type Limits Name + ; ! - Hourly Value""" + +sch_type_limits = """ScheduleTypeLimits, + name_to_change, ! - Name + , ! - Lower Limit Value {BasedOnField A3} + , ! - Upper Limit Value {BasedOnField A3} + , ! - Numeric Type + None; ! - Unit Type""" + +sch_compact_default = """Schedule:Compact, + name_to_change, !- Name + , !- Schedule Type Limits Name + , !- Field 1 + , !- Field 2 + , !- Field 3 + 0; """ + +zone_eqlist_default = """ZoneHVAC:EquipmentList, + name_to_change, !- Name + , !- Zone Equipment Object Type + , !- Zone Equipment Name + 1, !- Zone Equipment Cooling Sequence + 1; !- Zone Equipment Heating or No-Load Sequence""" + +zone_eqconnect_default = """ZoneHVAC:EquipmentConnections, + name_to_change, !- Zone Name + , !- Zone Conditioning Equipment List Name + , !- Zone Air Inlet Node or NodeList Name + , !- Zone Air Exhaust Node or NodeList Name + name_to_change, !- Zone Air Node Name + name_to_change; !- Zone Return Air Node Name""" + +zonehvac_ideallas_default = """ZoneHVAC:IdealLoadsAirSystem, + Zone1 Ideal Loads System, !- Name + , !- Availability Schedule Name + , !- Zone Supply Air Node Name + , !- Zone Exhaust Air Node Name + 50, !- Maximum Heating Supply Air Temperature {C} + 13, !- Minimum Cooling Supply Air Temperature {C} + 0.0156, !- Maximum Heating Supply Air Humidity Ratio {kgWater/kgDryAir} + 0.0077, !- Minimum Cooling Supply Air Humidity Ratio {kgWater/kgDryAir} + NoLimit, !- Heating Limit + , !- Maximum Heating Air Flow Rate {m3/s} + , !- Maximum Sensible Heating Capacity {W} + NoLimit, !- Cooling Limit + , !- Maximum Cooling Air Flow Rate {m3/s} + , !- Maximum Total Cooling Capacity {W} + , !- Heating Availability Schedule Name + , !- Cooling Availability Schedule Name + ConstantSensibleHeatRatio, !- Dehumidification Control Type + 0.7, !- Cooling Sensible Heat Ratio + None, !- Humidification Control Type + , !- Design Specification Outdoor Air Object Name + , !- Outdoor Air Inlet Node Name + None, !- Demand Controlled Ventilation Type + NoEconomizer, !- Outdoor Air Economizer Type + None, !- Heat Recovery Type + 0, !- Sensible Heat Recovery Effectiveness + 0; !- Latent Heat Recovery Effectiveness""" + +sz_default = """Sizing:Zone, + name_to_change, !- Zone or ZoneList Name + SupplyAirTemperature, !- Zone Cooling Design Supply Air Temperature Input Method + 14., !- Zone Cooling Design Supply Air Temperature {C} + , !- Zone Cooling Design Supply Air Temperature Difference {deltaC} + SupplyAirTemperature, !- Zone Heating Design Supply Air Temperature Input Method + 50., !- Zone Heating Design Supply Air Temperature {C} + , !- Zone Heating Design Supply Air Temperature Difference {deltaC} + 0.008, !- Zone Cooling Design Supply Air Humidity Ratio {kgWater/kgDryAir} + 0.008, !- Zone Heating Design Supply Air Humidity Ratio {kgWater/kgDryAir} + , !- Design Specification Outdoor Air Object Name + 0.0, !- Zone Heating Sizing Factor + 0.0, !- Zone Cooling Sizing Factor + DesignDay, !- Cooling Design Air Flow Method + 0, !- Cooling Design Air Flow Rate {m3/s} + , !- Cooling Minimum Air Flow per Zone Floor Area {m3/s-m2} + , !- Cooling Minimum Air Flow {m3/s} + , !- Cooling Minimum Air Flow Fraction + DesignDay, !- Heating Design Air Flow Method + 0, !- Heating Design Air Flow Rate {m3/s} + , !- Heating Maximum Air Flow per Zone Floor Area {m3/s-m2} + , !- Heating Maximum Air Flow {m3/s} + ; !- Heating Maximum Air Flow Fraction""" + +design_spec_airdist = """DesignSpecification:ZoneAirDistribution, + name_to_change, !- Name + 1, !- Zone Air Distribution Effectiveness in Cooling Mode {dimensionless} + 1; !- Zone Air Distribution Effectiveness in Heating Mode {dimensionless}""" + + +# Functions to add all the objects + + +def add_designspec_airdist(idf, name, cool_eff=1, heat_eff=1): + designspec = idf.add_object(design_spec_airdist) + designspec["name"] = name + designspec[1] = cool_eff + designspec[2] = heat_eff + + +def add_sizing_zone(idf, zone_zonel, input_cooling_method="SupplyAirTemperature", + input_heating_method="SupplyAirTemperature"): + sz = idf.add_object(sz_default) + + sz[0] = zone_zonel + sz[1] = input_cooling_method + sz[4] = input_heating_method + + return sz + + +def add_zone_ideal_airloads(idf, name, availability_sch, supply_node_name, designspec_airdist=None): + zone_ilas = idf.add_object(zonehvac_ideallas_default) + zone_ilas["name"] = name + zone_ilas["availability schedule name"] = availability_sch + zone_ilas["zone supply air node name"] = supply_node_name + zone_ilas["Design Specification Outdoor Air Object Name"] = designspec_airdist + + return zone_ilas + + +def add_sch_typelimits(idf, name, low_value, upper_value, numeric_type="Continuous", unit_type=None): + sch = idf.add_object(sch_type_limits) + sch["name"] = name + sch["lower limit value"] = low_value + sch["upper limit value"] = upper_value + sch["numeric type"] = numeric_type + sch["unit type"] = unit_type + + return sch + + +def add_sch_constant(idf, name, hourly_value, sch_type_limit=None): + sch = idf.add_object(sch_constant_default) + sch["name"] = name + sch["schedule type limits name"] = sch_type_limit + sch["hourly value"] = hourly_value + + return sch + + +def add_sch_compact(idf, name, value, through="12/31", for_days="AllDays", until="24:00", sch_type_limit=None): + sch = idf.add_object(sch_compact_default) + sch["name"] = name + sch["schedule type limits name"] = sch_type_limit + sch[2] = "Through: " + through + sch[3] = "For: " + for_days + sch[4] = "Until: " + until + sch[5] = value + + return sch + + +def add_thermostat_dual_setpoints(idf, name, heating_sch, cooling_sch): + th = idf.add_object("ThermostatSetpoint:DualSetpoint,") + th.add_field(name, "Name") + th.add_field(heating_sch, "Heating Setpoint Temperature Schedule Name") + th.add_field(cooling_sch, "Cooling Setpoint Temperature Schedule Name") + + return th + + +def add_zone_thermostat(idf, name, zone_zonelist, control_type_sch, control_name, + control_obj="ThermostatSetpoint:DualSetpoint"): + zone_th = idf.add_object(zone_thermostat_default) + zone_th["name"] = name + zone_th["Zone or ZoneList Name"] = zone_zonelist + zone_th["Control Type Schedule Name"] = control_type_sch + zone_th["Control 1 Object Type"] = control_obj + zone_th["Control 1 Name"] = control_name + + return zone_th + + +def add_zone_equipmentlist(idf, name, zone_eq_type=None, zone_eq=None, cool_seq=1, heat_seq=1): + eqlist = idf.add_object("ZoneHVAC:EquipmentList, ") + eqlist.add_field(name, "Name") + eqlist.add_field(zone_eq_type, "Zone Equipment 1 Object Type") + eqlist.add_field(zone_eq, "Zone Equipment 1 Name") + eqlist.add_field(cool_seq, "Zone Equipment 1 Cooling Sequence") + eqlist.add_field(heat_seq, "Zone Equipment 1 Heating or No-Load Sequence") + + return eqlist + + +def add_zone_equipmentconnection(idf, zone, zone_air_node, zone_return_node, zone_eqlist=None, zone_inlet_node=None, + zone_exhaust_node=None): + eqconnect = idf.add_object(zone_eqconnect_default) + eqconnect["zone name"] = zone + eqconnect["Zone Conditioning Equipment List Name"] = zone_eqlist + eqconnect["Zone Air Inlet Node or NodeList Name"] = zone_inlet_node + eqconnect["Zone Air Exhaust Node or NodeList Name"] = zone_exhaust_node + eqconnect["Zone Air Node Name"] = zone_air_node + eqconnect["Zone Return Air Node Name"] = zone_return_node + + return eqconnect diff --git a/bpeng/simulation/design_days.py b/bpeng/simulation/design_days.py new file mode 100644 index 0000000..f2b83c4 --- /dev/null +++ b/bpeng/simulation/design_days.py @@ -0,0 +1,200 @@ +""" +Design Days storage for New York + +author: Thomas +""" + +import oplus + +ddaylist = [ + """SizingPeriod:DesignDay, + NEW_YORK Ann Clg .4% Condns DB=>MWB, !- Name + 7, !- Month + 21, !- Day of Month + SummerDesignDay, !- Day Type + 32.1, !- Maximum Dry-Bulb Temperature {C} + 7.4, !- Daily Dry-Bulb Temperature Range {deltaC} + DefaultMultipliers, !- Dry-Bulb Temperature Range Modifier Type + , !- Dry-Bulb Temperature Range Modifier Day Schedule Name + Wetbulb, !- Humidity Condition Type + 23.1, !- Wetbulb or DewPoint at Maximum Dry-Bulb {C} + , !- Humidity Condition Day Schedule Name + , !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir} + , !- Enthalpy at Maximum Dry-Bulb {J/kg} + , !- Daily Wet-Bulb Temperature Range {deltaC} + 100642, !- Barometric Pressure {Pa} + 5.6, !- Wind Speed {m/s} + 230, !- Wind Direction {deg} + No, !- Rain Indicator + No, !- Snow Indicator + No, !- Daylight Saving Time Indicator + ASHRAETau, !- Solar Model Indicator + , !- Beam Solar Day Schedule Name + , !- Diffuse Solar Day Schedule Name + 0.541, !- ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) {dimensionless} + 1.8; !- ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) {dimensionless}""", + """SizingPeriod:DesignDay, + NEW_YORK Ann Clg .4% Condns DP=>MDB, !- Name + 7, !- Month + 21, !- Day of Month + SummerDesignDay, !- Day Type + 27, !- Maximum Dry-Bulb Temperature {C} + 7.4, !- Daily Dry-Bulb Temperature Range {deltaC} + DefaultMultipliers, !- Dry-Bulb Temperature Range Modifier Type + , !- Dry-Bulb Temperature Range Modifier Day Schedule Name + Dewpoint, !- Humidity Condition Type + 23.8, !- Wetbulb or DewPoint at Maximum Dry-Bulb {C} + , !- Humidity Condition Day Schedule Name + , !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir} + , !- Enthalpy at Maximum Dry-Bulb {J/kg} + , !- Daily Wet-Bulb Temperature Range {deltaC} + 100642, !- Barometric Pressure {Pa} + 5.6, !- Wind Speed {m/s} + 230, !- Wind Direction {deg} + No, !- Rain Indicator + No, !- Snow Indicator + No, !- Daylight Saving Time Indicator + ASHRAETau, !- Solar Model Indicator + , !- Beam Solar Day Schedule Name + , !- Diffuse Solar Day Schedule Name + 0.541, !- ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) {dimensionless} + 1.8; !- ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) {dimensionless}""", + """SizingPeriod:DesignDay, + NEW_YORK Ann Clg .4% Condns Enth=>MDB, !- Name + 7, !- Month + 21, !- Day of Month + SummerDesignDay, !- Day Type + 29.1, !- Maximum Dry-Bulb Temperature {C} + 7.4, !- Daily Dry-Bulb Temperature Range {deltaC} + DefaultMultipliers, !- Dry-Bulb Temperature Range Modifier Type + , !- Dry-Bulb Temperature Range Modifier Day Schedule Name + Enthalpy, !- Humidity Condition Type + , !- Wetbulb or DewPoint at Maximum Dry-Bulb {C} + , !- Humidity Condition Day Schedule Name + , !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir} + 75700, !- Enthalpy at Maximum Dry-Bulb {J/kg} + , !- Daily Wet-Bulb Temperature Range {deltaC} + 100642, !- Barometric Pressure {Pa} + 5.6, !- Wind Speed {m/s} + 230, !- Wind Direction {deg} + No, !- Rain Indicator + No, !- Snow Indicator + No, !- Daylight Saving Time Indicator + ASHRAETau, !- Solar Model Indicator + , !- Beam Solar Day Schedule Name + , !- Diffuse Solar Day Schedule Name + 0.541, !- ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) {dimensionless} + 1.8; !- ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) {dimensionless}""", + """SizingPeriod:DesignDay, + NEW_YORK Ann Clg .4% Condns WB=>MDB, !- Name + 7, !- Month + 21, !- Day of Month + SummerDesignDay, !- Day Type + 29.1, !- Maximum Dry-Bulb Temperature {C} + 7.4, !- Daily Dry-Bulb Temperature Range {deltaC} + DefaultMultipliers, !- Dry-Bulb Temperature Range Modifier Type + , !- Dry-Bulb Temperature Range Modifier Day Schedule Name + Wetbulb, !- Humidity Condition Type + 25, !- Wetbulb or DewPoint at Maximum Dry-Bulb {C} + , !- Humidity Condition Day Schedule Name + , !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir} + , !- Enthalpy at Maximum Dry-Bulb {J/kg} + , !- Daily Wet-Bulb Temperature Range {deltaC} + 100642, !- Barometric Pressure {Pa} + 5.6, !- Wind Speed {m/s} + 230, !- Wind Direction {deg} + No, !- Rain Indicator + No, !- Snow Indicator + No, !- Daylight Saving Time Indicator + ASHRAETau, !- Solar Model Indicator + , !- Beam Solar Day Schedule Name + , !- Diffuse Solar Day Schedule Name + 0.541, !- ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) {dimensionless} + 1.8; !- ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) {dimensionless}""", + """SizingPeriod:DesignDay, + NEW_YORK Ann Htg 99.6% Condns DB, !- Name + 1, !- Month + 21, !- Day of Month + WinterDesignDay, !- Day Type + -10.7, !- Maximum Dry-Bulb Temperature {C} + 0, !- Daily Dry-Bulb Temperature Range {deltaC} + DefaultMultipliers, !- Dry-Bulb Temperature Range Modifier Type + , !- Dry-Bulb Temperature Range Modifier Day Schedule Name + Wetbulb, !- Humidity Condition Type + -10.7, !- Wetbulb or DewPoint at Maximum Dry-Bulb {C} + , !- Humidity Condition Day Schedule Name + , !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir} + , !- Enthalpy at Maximum Dry-Bulb {J/kg} + , !- Daily Wet-Bulb Temperature Range {deltaC} + 100642, !- Barometric Pressure {Pa} + 7.5, !- Wind Speed {m/s} + 320, !- Wind Direction {deg} + No, !- Rain Indicator + No, !- Snow Indicator + No, !- Daylight Saving Time Indicator + ASHRAEClearSky, !- Solar Model Indicator + , !- Beam Solar Day Schedule Name + , !- Diffuse Solar Day Schedule Name + , !- ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) {dimensionless} + , !- ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) {dimensionless} + 0; !- Sky Clearness""", + """SizingPeriod:DesignDay, + NEW_YORK Ann Htg Wind 99.6% Condns WS=>MCDB, !- Name + 1, !- Month + 21, !- Day of Month + WinterDesignDay, !- Day Type + -3.2, !- Maximum Dry-Bulb Temperature {C} + 0, !- Daily Dry-Bulb Temperature Range {deltaC} + DefaultMultipliers, !- Dry-Bulb Temperature Range Modifier Type + , !- Dry-Bulb Temperature Range Modifier Day Schedule Name + Wetbulb, !- Humidity Condition Type + -3.2, !- Wetbulb or DewPoint at Maximum Dry-Bulb {C} + , !- Humidity Condition Day Schedule Name + , !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir} + , !- Enthalpy at Maximum Dry-Bulb {J/kg} + , !- Daily Wet-Bulb Temperature Range {deltaC} + 100642, !- Barometric Pressure {Pa} + 14.2, !- Wind Speed {m/s} + 320, !- Wind Direction {deg} + No, !- Rain Indicator + No, !- Snow Indicator + No, !- Daylight Saving Time Indicator + ASHRAEClearSky, !- Solar Model Indicator + , !- Beam Solar Day Schedule Name + , !- Diffuse Solar Day Schedule Name + , !- ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) {dimensionless} + , !- ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) {dimensionless} + 0; !- Sky Clearness""", + """SizingPeriod:DesignDay, + NEW_YORK Ann Hum_n 99.6% Condns DP=>MCDB, !- Name + 1, !- Month + 21, !- Day of Month + WinterDesignDay, !- Day Type + -8.9, !- Maximum Dry-Bulb Temperature {C} + 0, !- Daily Dry-Bulb Temperature Range {deltaC} + DefaultMultipliers, !- Dry-Bulb Temperature Range Modifier Type + , !- Dry-Bulb Temperature Range Modifier Day Schedule Name + Dewpoint, !- Humidity Condition Type + -20.8, !- Wetbulb or DewPoint at Maximum Dry-Bulb {C} + , !- Humidity Condition Day Schedule Name + , !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir} + , !- Enthalpy at Maximum Dry-Bulb {J/kg} + , !- Daily Wet-Bulb Temperature Range {deltaC} + 100642, !- Barometric Pressure {Pa} + 7.5, !- Wind Speed {m/s} + 320, !- Wind Direction {deg} + No, !- Rain Indicator + No, !- Snow Indicator + No, !- Daylight Saving Time Indicator + ASHRAEClearSky, !- Solar Model Indicator + , !- Beam Solar Day Schedule Name + , !- Diffuse Solar Day Schedule Name + , !- ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) {dimensionless} + , !- ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) {dimensionless} + 0; !- Sky Clearness""" +] + + +def add_dday(idf, dday_list=ddaylist): + for dday in dday_list: + idf.add_object(dday) diff --git a/bpeng/simulation/geometry.py b/bpeng/simulation/geometry.py new file mode 100644 index 0000000..4903c23 --- /dev/null +++ b/bpeng/simulation/geometry.py @@ -0,0 +1,184 @@ +""" +Geometry operations to convert multi-polygon (list of coordinates) into the correct input to be further +processed by the notebook so the geometry of the buildings are added to the IDF (EnergyPlus input) file. + +author: Thomas +mods: Michel - add functions to calculate distance between 2 points for 2D and 3D coordinates (3/24/2017) +""" + +import numpy as np +import math +from geopy.distance import vincenty + + +def reverse_list(lst): + return [lst[-i] for i in range(1, len(lst) + 1)] + + +def walls_vertex(xy, hl, hh): + low = [(x, y, hl) for x, y in xy.dropna()] + high = [(x, y, hh) for x, y in xy.dropna()] + res = [] + for i in range(len(low) - 1): + res.append(list(low[i:i + 2] + reverse_list(high[i:i + 2]))) + return res + + +def floor_vertex(xy, height): + return [(x, y, height) for x, y in xy.dropna()] + + +def ceiling_vertex(xy, height): + return reverse_list(floor_vertex(xy, height)) + + +def barycentre_coord(coords): + """ + coords: list + [(x,y,z) for x,y,z one point coordinate] + """ + xl = [] + yl = [] + zl = [] + for x, y, z in coords: + xl.append(x) + yl.append(y) + zl.append(z) + return np.mean(xl), np.mean(yl), np.mean(zl) + + +def homothety(coords, ratio): + """ + coords: list + [(x,y,z) for x,y,z one point coordinate] + ratio: float + % of area to be occupied by the new surface which we try to calculate the coordinates. + """ + r = np.sqrt(ratio) + matrix_homothety = np.diagflat([r, r, r, 1]) + old_coords = np.array(coords) + return [tuple(np.dot(matrix_homothety, ([v[0], v[1], v[2], 1]))[:-1]) for v in old_coords] + + +def translation(coords, translation_vector): + """ + coords: list + [(x,y,z) for x,y,z one point coordinate] + """ + xt = translation_vector[0] + yt = translation_vector[1] + zt = translation_vector[2] + return [(x + xt, y + yt, z + zt) for x, y, z in coords] + + +def offset_center_ratio(ratio, coords): + """ + coords: list + [(x,y,z) for x,y,z one point coordinate] + """ + # Homothety + new_coords = homothety(coords, ratio) + + # Translation + old_barycentre = barycentre_coord(coords) + new_barycentre = barycentre_coord(new_coords) + translation_vector = [old_barycentre[i] - new_barycentre[i] for i in range(len(new_barycentre))] + new_coords = translation(new_coords, translation_vector) + + return new_coords + + +def reverse_idf_obj(obj): + obj[1:len(obj) - 1] = reverse_list(obj[1:len(obj) - 1]) + return obj + + +def twodimdistance(p0, p1): + return math.sqrt((p0[0] - p1[0])**2 + (p0[1] - p1[1])**2) + + +def threedimdistance(p0, p1): + return math.sqrt((p0[0] - p1[0])**2 + (p0[1] - p1[1])**2 + (p0[2] - p1[2])**2) + + +def fix_degenerate_surface(geom_div_col): + """ + Calculate length of vertices of building footprint geometry (2D points) + Remove points when length is < 0.01 [meters] + + Parameters + ---------- + geom_div_col: pandas DataFrame + Building footprint geometry obtained when parsing building 2D shapefile + row index = Building Identification Number (float) + column name = numbered (int) + value = 2D points coordinates (tuples) [m] + + Returns + ---------- + geom_div_col: pandas DataFrame + New building footprint geometry without points when length is < 0.01 [m] (changed to 'None') + """ + # Loop for each row (buildings) + for bin_ in geom_div_col.index: + deg_vert = [] + for i in range(len(geom_div_col.columns)): + if geom_div_col.loc[bin_, i] is not None: + # Skip last point + if (i == len(geom_div_col.columns)-1) or (geom_div_col.loc[bin_,i+1] is None): + continue + else: + # Calculate distance between current point and next point + temp_dist = twodimdistance(geom_div_col.loc[bin_,i], geom_div_col.loc[bin_,i+1]) + # Record column number for distance below threshold + if temp_dist < 0.01: + deg_vert.append(i+1) + # Make point equal to 'None' to prevent degenerate surfaces + for j in deg_vert: + geom_div_col.loc[bin_, j] = None + return geom_div_col + + +def coord_to_meters(): + """ + Convert Earth degree coordinates to meters + + Parameters + ---------- + N/A + + Returns + ---------- + list of floats [m] + [longitude in meter, latitude in meter] + """ + a = (41., -74.) + b = (41., -75.) + conversion_long = vincenty(a, b).meters # meters for 1 longitude degree + c = (41., -74.) + d = (42., -74.) + conversion_lat = vincenty(c, d).meters # meters for 1 latitude degree + return (conversion_long, conversion_lat) + + +def tuple_convert_float(x, conversion_long, conversion_lat): + """ + Convert tuple content to float + Convert degree coordinates to meters + + Parameters + ---------- + x: tuple + Coordinate 2D in degrees + conversion_long: float + conversion factor from longitude degree coordinate to distance in meters + conversion_lat: float + Conversion factor from latitude degree coordinate to distance in meter + + Returns + ---------- + tuple of floats [m] + """ + if x is not None: + x = x.split(' ') + return (float(x[0])*conversion_long, float(x[1])*conversion_lat) diff --git a/bpeng/simulation/initial_idf/empty_start.idf b/bpeng/simulation/initial_idf/empty_start.idf new file mode 100644 index 0000000..9056b48 --- /dev/null +++ b/bpeng/simulation/initial_idf/empty_start.idf @@ -0,0 +1,2653 @@ +Version, + 8.5; !- Version Identifier + +LifeCycleCost:Parameters, + {c86b7012-7c52-4299-83a1-49a8abd76e8d}, !- Name + EndOfYear, !- Discounting Convention + ConstantDollar, !- Inflation Approach + 0.03, !- Real Discount Rate + , !- Nominal Discount Rate + , !- Inflation + , !- Base Date Month + 2011, !- Base Date Year + , !- Service Date Month + 2011, !- Service Date Year + 25, !- Length of Study Period in Years + , !- Tax rate + None; !- Depreciation Method + +LifeCycleCost:UsePriceEscalation, + U.S. Avg Commercial-Electricity, !- Name + Electricity, !- Resource + 2011, !- Escalation Start Year + January, !- Escalation Start Month + 0.9838, !- Year Escalation 1 + 0.9730, !- Year Escalation 2 + 0.9632, !- Year Escalation 3 + 0.9611, !- Year Escalation 4 + 0.9571, !- Year Escalation 5 + 0.9553, !- Year Escalation 6 + 0.9539, !- Year Escalation 7 + 0.9521, !- Year Escalation 8 + 0.9546, !- Year Escalation 9 + 0.9550, !- Year Escalation 10 + 0.9553, !- Year Escalation 11 + 0.9564, !- Year Escalation 12 + 0.9575, !- Year Escalation 13 + 0.9596, !- Year Escalation 14 + 0.9618, !- Year Escalation 15 + 0.9614, !- Year Escalation 16 + 0.9618, !- Year Escalation 17 + 0.9618, !- Year Escalation 18 + 0.9593, !- Year Escalation 19 + 0.9589, !- Year Escalation 20 + 0.9607, !- Year Escalation 21 + 0.9625, !- Year Escalation 22 + 0.9650, !- Year Escalation 23 + 0.9708, !- Year Escalation 24 + 0.9751, !- Year Escalation 25 + 0.9762, !- Year Escalation 26 + 0.9766, !- Year Escalation 27 + 0.9766, !- Year Escalation 28 + 0.9769, !- Year Escalation 29 + 0.9773; !- Year Escalation 30 + +LifeCycleCost:UsePriceEscalation, + U.S. Avg Commercial-Distillate Oil, !- Name + FuelOil#1, !- Resource + 2011, !- Escalation Start Year + January, !- Escalation Start Month + 0.9714, !- Year Escalation 1 + 0.9730, !- Year Escalation 2 + 0.9942, !- Year Escalation 3 + 1.0164, !- Year Escalation 4 + 1.0541, !- Year Escalation 5 + 1.0928, !- Year Escalation 6 + 1.1267, !- Year Escalation 7 + 1.1580, !- Year Escalation 8 + 1.1792, !- Year Escalation 9 + 1.1967, !- Year Escalation 10 + 1.2200, !- Year Escalation 11 + 1.2333, !- Year Escalation 12 + 1.2566, !- Year Escalation 13 + 1.2709, !- Year Escalation 14 + 1.2826, !- Year Escalation 15 + 1.2985, !- Year Escalation 16 + 1.3102, !- Year Escalation 17 + 1.3250, !- Year Escalation 18 + 1.3261, !- Year Escalation 19 + 1.3282, !- Year Escalation 20 + 1.3324, !- Year Escalation 21 + 1.3356, !- Year Escalation 22 + 1.3431, !- Year Escalation 23 + 1.3510, !- Year Escalation 24 + 1.3568, !- Year Escalation 25 + 1.3606, !- Year Escalation 26 + 1.3637, !- Year Escalation 27 + 1.3674, !- Year Escalation 28 + 1.3706, !- Year Escalation 29 + 1.3743; !- Year Escalation 30 + +LifeCycleCost:UsePriceEscalation, + U.S. Avg Commercial-Residual Oil, !- Name + FuelOil#2, !- Resource + 2011, !- Escalation Start Year + January, !- Escalation Start Month + 0.8469, !- Year Escalation 1 + 0.8257, !- Year Escalation 2 + 0.8681, !- Year Escalation 3 + 0.8988, !- Year Escalation 4 + 0.9289, !- Year Escalation 5 + 0.9604, !- Year Escalation 6 + 0.9897, !- Year Escalation 7 + 1.0075, !- Year Escalation 8 + 1.0314, !- Year Escalation 9 + 1.0554, !- Year Escalation 10 + 1.0861, !- Year Escalation 11 + 1.1278, !- Year Escalation 12 + 1.1497, !- Year Escalation 13 + 1.1620, !- Year Escalation 14 + 1.1743, !- Year Escalation 15 + 1.1852, !- Year Escalation 16 + 1.1948, !- Year Escalation 17 + 1.2037, !- Year Escalation 18 + 1.2071, !- Year Escalation 19 + 1.2119, !- Year Escalation 20 + 1.2139, !- Year Escalation 21 + 1.2194, !- Year Escalation 22 + 1.2276, !- Year Escalation 23 + 1.2365, !- Year Escalation 24 + 1.2420, !- Year Escalation 25 + 1.2461, !- Year Escalation 26 + 1.2509, !- Year Escalation 27 + 1.2550, !- Year Escalation 28 + 1.2591, !- Year Escalation 29 + 1.2638; !- Year Escalation 30 + +LifeCycleCost:UsePriceEscalation, + U.S. Avg Commercial-Natural gas, !- Name + NaturalGas, !- Resource + 2011, !- Escalation Start Year + January, !- Escalation Start Month + 0.9823, !- Year Escalation 1 + 0.9557, !- Year Escalation 2 + 0.9279, !- Year Escalation 3 + 0.9257, !- Year Escalation 4 + 0.9346, !- Year Escalation 5 + 0.9412, !- Year Escalation 6 + 0.9512, !- Year Escalation 7 + 0.9645, !- Year Escalation 8 + 0.9856, !- Year Escalation 9 + 1.0067, !- Year Escalation 10 + 1.0222, !- Year Escalation 11 + 1.0410, !- Year Escalation 12 + 1.0610, !- Year Escalation 13 + 1.0787, !- Year Escalation 14 + 1.0942, !- Year Escalation 15 + 1.1098, !- Year Escalation 16 + 1.1220, !- Year Escalation 17 + 1.1308, !- Year Escalation 18 + 1.1386, !- Year Escalation 19 + 1.1486, !- Year Escalation 20 + 1.1619, !- Year Escalation 21 + 1.1763, !- Year Escalation 22 + 1.1918, !- Year Escalation 23 + 1.2118, !- Year Escalation 24 + 1.2284, !- Year Escalation 25 + 1.2439, !- Year Escalation 26 + 1.2605, !- Year Escalation 27 + 1.2772, !- Year Escalation 28 + 1.2938, !- Year Escalation 29 + 1.3115; !- Year Escalation 30 + +LifeCycleCost:UsePriceEscalation, + U.S. Avg Commercial-Coal, !- Name + Coal, !- Resource + 2011, !- Escalation Start Year + January, !- Escalation Start Month + 0.9970, !- Year Escalation 1 + 1.0089, !- Year Escalation 2 + 1.0089, !- Year Escalation 3 + 0.9941, !- Year Escalation 4 + 0.9941, !- Year Escalation 5 + 1.0000, !- Year Escalation 6 + 1.0030, !- Year Escalation 7 + 1.0059, !- Year Escalation 8 + 1.0089, !- Year Escalation 9 + 1.0119, !- Year Escalation 10 + 1.0148, !- Year Escalation 11 + 1.0178, !- Year Escalation 12 + 1.0208, !- Year Escalation 13 + 1.0267, !- Year Escalation 14 + 1.0297, !- Year Escalation 15 + 1.0356, !- Year Escalation 16 + 1.0415, !- Year Escalation 17 + 1.0534, !- Year Escalation 18 + 1.0564, !- Year Escalation 19 + 1.0593, !- Year Escalation 20 + 1.0653, !- Year Escalation 21 + 1.0712, !- Year Escalation 22 + 1.0742, !- Year Escalation 23 + 1.0801, !- Year Escalation 24 + 1.0831, !- Year Escalation 25 + 1.0831, !- Year Escalation 26 + 1.0861, !- Year Escalation 27 + 1.0890, !- Year Escalation 28 + 1.0920, !- Year Escalation 29 + 1.0950; !- Year Escalation 30 + +Building, + Building 1, !- Name + , !- North Axis {deg} + , !- Terrain + , !- Loads Convergence Tolerance Value + , !- Temperature Convergence Tolerance Value {deltaC} + , !- Solar Distribution + , !- Maximum Number of Warmup Days + ; !- Minimum Number of Warmup Days + +SimulationControl, + No, !- Do Zone Sizing Calculation + No, !- Do System Sizing Calculation + No, !- Do Plant Sizing Calculation + Yes, !- Run Simulation for Sizing Periods + Yes; !- Run Simulation for Weather File Run Periods + +! ProgramControl, +! 1; !- Number of Threads Allowed + +Sizing:Parameters, + 1.25, !- Heating Sizing Factor + 1.15; !- Cooling Sizing Factor + +RunPeriod, + Run Period 1, !- Name + 1, !- Begin Month + 1, !- Begin Day of Month + 12, !- End Month + 31, !- End Day of Month + Thursday, !- Day of Week for Start Day + No, !- Use Weather File Holidays and Special Days + No, !- Use Weather File Daylight Saving Period + No, !- Apply Weekend Holiday Rule + Yes, !- Use Weather File Rain Indicators + Yes, !- Use Weather File Snow Indicators + 1; !- Number of Times Runperiod to be Repeated + +GlobalGeometryRules, + UpperLeftCorner, !- Starting Vertex Position + Counterclockwise, !- Vertex Entry Direction + Relative, !- Coordinate System + Relative, !- Daylighting Reference Point Coordinate System + Relative; !- Rectangular Surface Coordinate System + +OutputControl:Table:Style, + XMLAndHTML, !- Column Separator + JtoKWH; !- Unit Conversion + +Output:Table:SummaryReports, + AllSummaryAndSizingPeriod; !- Report Name 1 + +Output:VariableDictionary, + IDF, !- Key Field + Unsorted; !- Sort Option + +Output:SQLite, + SimpleAndTabular; !- Option Type + +Output:Diagnostics, + DisplayAllWarnings, + DisplayExtraWarnings; + +LifeCycleCost:NonrecurringCost, + Default Cost, !- Name + Construction, !- Category + 0, !- Cost + ServicePeriod; !- Start of Costs + + +ScheduleTypeLimits, + ActivityLevel, !- Name + 0, !- Lower Limit Value {BasedOnField A3} + , !- Upper Limit Value {BasedOnField A3} + Continuous, !- Numeric Type + activitylevel; !- Unit Type + +ScheduleTypeLimits, + ActivityLevel 12, !- Name + 0, !- Lower Limit Value {BasedOnField A3} + , !- Upper Limit Value {BasedOnField A3} + Continuous, !- Numeric Type + activitylevel; !- Unit Type + +ScheduleTypeLimits, + ActivityLevel 13, !- Name + 0, !- Lower Limit Value {BasedOnField A3} + , !- Upper Limit Value {BasedOnField A3} + Continuous, !- Numeric Type + activitylevel; !- Unit Type + +ScheduleTypeLimits, + ActivityLevel 5, !- Name + 0, !- Lower Limit Value {BasedOnField A3} + , !- Upper Limit Value {BasedOnField A3} + Continuous, !- Numeric Type + activitylevel; !- Unit Type + +ScheduleTypeLimits, + Fraction, !- Name + 0, !- Lower Limit Value {BasedOnField A3} + 1, !- Upper Limit Value {BasedOnField A3} + CONTINUOUS; !- Numeric Type + +ScheduleTypeLimits, + Fractional, !- Name + 0, !- Lower Limit Value {BasedOnField A3} + 1, !- Upper Limit Value {BasedOnField A3} + Continuous; !- Numeric Type + +ScheduleTypeLimits, + Temperature 11, !- Name + , !- Lower Limit Value {BasedOnField A3} + , !- Upper Limit Value {BasedOnField A3} + Continuous, !- Numeric Type + temperature; !- Unit Type + +ScheduleTypeLimits, + Temperature 3, !- Name + , !- Lower Limit Value {BasedOnField A3} + , !- Upper Limit Value {BasedOnField A3} + Continuous, !- Numeric Type + temperature; !- Unit Type + +ScheduleTypeLimits, + Temperature 36, !- Name + , !- Lower Limit Value {BasedOnField A3} + , !- Upper Limit Value {BasedOnField A3} + Continuous, !- Numeric Type + temperature; !- Unit Type + +ScheduleTypeLimits, + Temperature 37, !- Name + , !- Lower Limit Value {BasedOnField A3} + , !- Upper Limit Value {BasedOnField A3} + Continuous, !- Numeric Type + temperature; !- Unit Type + +ScheduleTypeLimits, + Temperature 4, !- Name + , !- Lower Limit Value {BasedOnField A3} + , !- Upper Limit Value {BasedOnField A3} + Continuous, !- Numeric Type + temperature; !- Unit Type + +ScheduleTypeLimits, + Temperature 5, !- Name + , !- Lower Limit Value {BasedOnField A3} + , !- Upper Limit Value {BasedOnField A3} + Continuous, !- Numeric Type + temperature; !- Unit Type + +Schedule:Constant, + Always On Discrete, !- Name + , !- Schedule Type Limits Name + 1; !- Hourly Value + +Schedule:Constant, + Always Off Discrete, !- Name + , !- Schedule Type Limits Name + 0; !- Hourly Value + +Schedule:Constant, + Always On Continuous, !- Name + , !- Schedule Type Limits Name + 1; !- Hourly Value + +Site:Location, + Site 1, !- Name + 0, !- Latitude {deg} + 0, !- Longitude {deg} + 0, !- Time Zone {hr} + 0; !- Elevation {m} + + +!- =========== ALL OBJECTS IN CLASS: GROUNDTEMPERATURES =========== +! +! Ground temperature object produced by /tools/bin/gt2idf /phome/comstd/_p.gtp/state.analyses/slab/output/Zone4A_res_R0_0ftV_ApartmentMidRise_Baltimore_STD2004.gtp +Site:GroundTemperature:BuildingSurface, + 19.99, !- January Ground Temperature {C} + 19.92, !- February Ground Temperature {C} + 20.10, !- March Ground Temperature {C} + 20.24, !- April Ground Temperature {C} + 20.48, !- May Ground Temperature {C} + 22.81, !- June Ground Temperature {C} + 23.29, !- July Ground Temperature {C} + 23.40, !- August Ground Temperature {C} + 23.33, !- September Ground Temperature {C} + 21.03, !- October Ground Temperature {C} + 20.52, !- November Ground Temperature {C} + 20.17; !- December Ground Temperature {C} + + +!================================================================================================================= +! ***PRE 1980 OPAQUE CONSTRUCTIONS AND MATERIALS*** +! Envelope: Envelope thermal properties vary with climate according to Briggs et al. (1987). +! Opaque constructions: Steel frame wall; Insulation entirely above deck; slab-on-grade floor + +! Exterior Walls +Construction, + Steel Frame Res Ext Wall_wood siding_pre1980, !- Name + Wood Siding, !- Outside Layer + Steel Frame Res Wall Insulation_pre1980, !- Layer 2 + 1/2IN Gypsum; !- Layer 3 + +Construction, + Steel Frame Res Ext Wall_stucco_pre1980, !- Name + 1IN Stucco, !- Outside Layer + Steel Frame Res Wall Insulation_pre1980, !- Layer 2 + 1/2IN Gypsum; !- Layer 3 + +Material, + Steel Frame Res Wall Insulation_pre1980, !- Name + MediumRough, !- Roughness + 0.03280276832256, !- Thickness {m} + 0.049, !- Conductivity {W/m-K} + 265.0000, !- Density {kg/m3} + 836.8000, !- Specific Heat {J/kg-K} + 0.9000, !- Thermal Absorptance + 0.7000, !- Solar Absorptance + 0.7000; !- Visible Absorptance + +! Roof +Construction, + IEAD Res Roof_pre1980, !- Name + Roof Membrane, !- Layer 1 + IEAD Res Roof Insulation_pre1980, !- Layer 2 + Metal Decking; !- Layer 3 + +Material, + IEAD Res Roof Insulation_pre1980, !- Name + MediumRough, !- Roughness + 0.0880290133462796, !- Thickness {m} + 0.049, !- Conductivity {W/m-K} + 265.0000, !- Density + 836.8000, !- Specific Heat + 0.9000, !- Thermal Absorptance + 0.7000, !- Solar Absorptance + 0.7000; !- Visible Absorptance + +! ***WINDOW/DOOR CONSTRUCTIONS AND MATERIALS*** + +Construction, + Window Res Operable_pre1980, !- Name + Res Operable Assembly Window_pre1980; !- Outside Layer + +WindowMaterial:SimpleGlazingSystem, + Res Operable Assembly Window_pre1980, !- Name + 6.92716, !- U-Factor + 0.54, !- Solar Heat Gain Coefficient + ; !- Visible Transmittance + +! ***POST 1980 OPAQUE CONSTRUCTIONS AND MATERIALS*** +! Envelope: Envelope thermal properties vary with climate according to ASHRAE Standard 90.1-1989 residential. +! Opaque constructions: Steel frame wall; Insulation entirely above deck; slab-on-grade floor + +! Exterior Walls +Construction, + Steel Frame Res Ext Wall_wood siding_post1980, !- Name + Wood Siding, !- Outside Layer + Steel Frame Res Wall Insulation_post1980, !- Layer 2 + 1/2IN Gypsum; !- Layer 3 + +Construction, + Steel Frame Res Ext Wall_stucco_post1980, !- Name + 1IN Stucco, !- Outside Layer + Steel Frame Res Wall Insulation_post1980, !- Layer 2 + 1/2IN Gypsum; !- Layer 3 + +Material, + Steel Frame Res Wall Insulation_post1980, !- Name + MediumRough, !- Roughness + 0.0812847864409827, !- Thickness {m} + 0.049, !- Conductivity {W/m-K} + 265.0000, !- Density {kg/m3} + 836.8000, !- Specific Heat {J/kg-K} + 0.9000, !- Thermal Absorptance + 0.7000, !- Solar Absorptance + 0.7000; !- Visible Absorptance + +! Roof +Construction, + IEAD Res Roof_post1980, !- Name + Roof Membrane, !- Layer 1 + IEAD Res Roof Insulation_post1980, !- Layer 2 + Metal Decking; !- Layer 3 + +Material, + IEAD Res Roof Insulation_post1980, !- Name + MediumRough, !- Roughness + 0.13647215254079, !- Thickness {m} + 0.049, !- Conductivity {W/m-K} + 265.0000, !- Density + 836.8000, !- Specific Heat + 0.9000, !- Thermal Absorptance + 0.7000, !- Solar Absorptance + 0.7000; !- Visible Absorptance + +! ***WINDOW/DOOR CONSTRUCTIONS AND MATERIALS*** + +Construction, + Window Res Operable_post1980, !- Name + Res Operable Assembly Window_post1980; !- Outside Layer + +WindowMaterial:SimpleGlazingSystem, + Res Operable Assembly Window_post1980, !- Name + 3.35002, !- U-Factor + 0.36, !- Solar Heat Gain Coefficient + ; !- Visible Transmittance + +! ***COMMON CONSTRUCTIONS FOR PRE and POST1980 BUILDINGS*** + +! Slab on grade, unheated + Construction, + ext-slab, !- Name + HW CONCRETE, !- Outside Layer + CP02 CARPET PAD; !- Layer 2 + +! Interior Walls +Construction, + int-walls, !- Name + 1/2IN Gypsum, !- Outside Layer + 1/2IN Gypsum; !- Layer 2 + +! Interior Floors +Construction, + INT-FLOOR-TOPSIDE, !- Name + MAT-CC05 4 HW CONCRETE, !- Outside Layer + CP02 CARPET PAD; !- Layer 2 + +Construction, + INT-FLOOR-UNDERSIDE, !- Name + CP02 CARPET PAD, !- Outside Layer + MAT-CC05 4 HW CONCRETE; !- Layer 2 + +! ***COMMON CONSTRUCTIONS AND MATERIALS*** + +Construction, + AIR-WALL, !- Name + MAT-AIR-WALL; !- Outside Layer + +Construction, + InteriorFurnishings, !- Name + Std Wood 6inch; !- Outside Layer + +Material, + Std Wood 6inch, !- Name + MediumSmooth, !- Roughness + 0.15, !- Thickness {m} + 0.12, !- Conductivity {W/m-K} + 540.0000, !- Density {kg/m3} + 1210, !- Specific Heat {J/kg-K} + 0.9000000, !- Thermal Absorptance + 0.7000000, !- Solar Absorptance + 0.7000000; !- Visible Absorptance! Common Materials + +Material, + Wood Siding, !- Name + MediumSmooth, !- Roughness + 0.0100, !- Thickness {m} + 0.1100, !- Conductivity {W/m-K} + 544.6200, !- Density {kg/m3} + 1210.0000, !- Specific Heat {J/kg-K} + 0.9000, !- Thermal Absorptance + 0.7800, !- Solar Absorptance + 0.7800; !- Visible Absorptance + +Material, + 1/2IN Gypsum, !- Name + Smooth, !- Roughness + 0.0127, !- Thickness {m} + 0.1600, !- Conductivity {W/m-K} + 784.9000, !- Density {kg/m3} + 830.0000, !- Specific Heat {J/kg-K} + 0.9000, !- Thermal Absorptance + 0.9200, !- Solar Absorptance + 0.9200; !- Visible Absorptance + +Material, + 1IN Stucco, !- Name + Smooth, !- Roughness + 0.0253, !- Thickness + 0.6918, !- Conductivity + 1858.0000, !- Density + 837.0000, !- Specific Heat + 0.9000, !- Thermal Absorptance + 0.9200, !- Solar Absorptance + 0.9200; !- Visible Absorptance + +Material, + 8IN CONCRETE HW, !- Name + Rough, !- Roughness + 0.2032, !- Thickness {m} + 1.3110, !- Conductivity {W/m-K} + 2240.0000, !- Density {kg/m3} + 836.8000, !- Specific Heat {J/kg-K} + 0.9000, !- Thermal Absorptance + 0.7000, !- Solar Absorptance + 0.7000; !- Visible Absorptance + +Material, + Metal Siding, !- Name + Smooth, !- Roughness + 0.0015, !- Thickness + 44.9600, !- Conductivity + 7688.8600, !- Density + 410.0000, !- Specific Heat + 0.9000, !- Thermal Absorptance + 0.2000, !- Solar Absorptance + 0.2000; !- Visible Absorptance + +Material, + HW CONCRETE, !- Name + Rough, !- Roughness + 0.1016, !- Thickness {m} + 1.3110, !- Conductivity {W/m-K} + 2240.0000, !- Density {kg/m3} + 836.8000, !- Specific Heat {J/kg-K} + 0.9000, !- Thermal Absorptance + 0.7000, !- Solar Absorptance + 0.7000; !- Visible Absorptance + +Material:NoMass, + CP02 CARPET PAD, !- Name + VeryRough, !- Roughness + 0.2165, !- Thermal Resistance {(m2-K)/W} + 0.9000, !- Thermal Absorptance + 0.7000, !- Solar Absorptance + 0.8000; !- Visible Absorptance + +Material, + Roof Membrane, !- Name + VeryRough, !- Roughness + 0.0095, !- Thickness {m} + 0.1600, !- Conductivity {W/m-K} + 1121.2900, !- Density {kg/m3} + 1460.0000, !- Specific Heat {J/kg-K} + 0.9000, !- Thermal Absorptance + 0.7000, !- Solar Absorptance + 0.7000; !- Visible Absorptance + +Material, + Metal Decking, !- Name + MediumSmooth, !- Roughness + 0.0015, !- Thickness {m} + 45.0060, !- Conductivity {W/m-K} + 7680.0000, !- Density {kg/m3} + 418.4000, !- Specific Heat {J/kg-K} + 0.9000, !- Thermal Absorptance + 0.7000, !- Solar Absorptance + 0.3000; !- Visible Absorptance + +Material, + Metal Roofing, !- Name + MediumSmooth, !- Roughness + 0.0015, !- Thickness + 45.0060, !- Conductivity + 7680.0000, !- Density + 418.4000, !- Specific Heat + 0.9000, !- Thermal Absorptance + 0.7000, !- Solar Absorptance + 0.3000; !- Visible Absorptance + +Material, + MAT-CC05 4 HW CONCRETE, !- Name + Rough, !- Roughness + 0.1016, !- Thickness {m} + 1.3110, !- Conductivity {W/m-K} + 2240.0000, !- Density {kg/m3} + 836.8000, !- Specific Heat {J/kg-K} + 0.9000, !- Thermal Absorptance + 0.7000, !- Solar Absorptance + 0.7000; !- Visible Absorptance + +Material:NoMass, + MAT-AIR-WALL, !- Name + Rough, !- Roughness + 0.2079491, !- Thermal Resistance {m2-K/W} + 0.9, !- Thermal Absorptance + 0.7; !- Solar Absorptance + +!============================================================================================================ +!============================================================================================================ +! Below is a Constructions Database from the Building Energy Codes Program (DOE energycodes.gov) +! This is based on ASHRAE 90.1 2004, 2007, 2010 and 2013 +! Opaque Constructions: OpaqueLibraryScript_v30.idf,v 1.5 2010/10/21 19:30:30 +! Window Constructions: WindowsLibrary_v30.idf,v 1.6 2010/10/16 00:03:25 +!- =========== Opaque Constructions =========== +! ------------------------------------------------------------------ +! $Id: OpaqueLibraryScript_v30.idf,v 1.5 2010/10/21 19:30:30 atha577 Exp $ +! $Log: OpaqueLibraryScript_v30.idf,v $ +! Revision 1.5 2010/10/21 19:30:30 atha577 +! Removed bb constructions for skylights. +! +! Revision 1.4 2010/10/16 00:49:56 atha577 +! Minor change to bb code. +! +! Revision 1.3 2010/10/16 00:08:35 atha577 +! Added bb skylight constructions. +! +! Revision 1.2 2010/01/20 21:56:42 d3l143 +! reset R value of semi-heated Roof to 0.001 if the R values goes below 0.001. V4.0 has a 0.001 threshold with it. +! +! Revision 1.1 2010/01/20 21:49:30 d3l143 +! Initial revision +! +! Note: +! January 20, 2010: We experienced a problem in upgrading Warehouse from V3.0 to V4.0. +! The R value of the semiheated roof goes to around 0.0002 for Miami and Ryihad which V4.0 compliants that it is below 0.001. +! This was not a problem for V3.0. Here we implemented a temporal solution to re-set the r value to 0.001 when it is below it. +! ------------------------------------------------------------------ +! +!- =========== ALL OBJECTS IN CLASS: MATERIAL:REGULAR =========== + + Material, + AC02 Acoustic Ceiling, !- Name + MediumSmooth, !- Roughness + 1.2700000E-02, !- Thickness {m} + 5.7000000E-02, !- Conductivity {W/m-K} + 288.0000, !- Density {kg/m3} + 1339.000, !- Specific Heat {J/kg-K} + 0.9000000, !- Thermal Absorptance + 0.7000000, !- Solar Absorptance + 0.2000000; !- Visible Absorptance + + Material, + F07 25mm stucco, !- Name + Smooth, !- Roughness + 0.0254, !- Thickness {m} + 0.72, !- Conductivity {W/m-K} + 1856, !- Density {kg/m3} + 840, !- Specific Heat {J/kg-K} + 0.9, !- Thermal Absorptance + 0.7, !- Solar Absorptance + 0.7; !- Visible Absorptance + + Material, + F08 Metal roof surface, !- Name + Smooth, !- Roughness + 0.0008, !- Thickness {m} + 45.28, !- Conductivity {W/m-K} + 7824, !- Density {kg/m3} + 500, !- Specific Heat {J/kg-K} + 0.9, !- Absorptance:Thermal + 0.7; !- Absorptance:Solar + + Material, + F12 Asphalt shingles, !- Name + VeryRough, !- Roughness + 0.0032, !- Thickness {m} + 0.04, !- Conductivity {W/m-K} + 1120, !- Density {kg/m3} + 1260, !- Specific Heat {J/kg-K} + 0.9, !- Absorptance:Thermal + 0.7; !- Absorptance:Solar + + Material, + F13 Built-up roofing, !- Name + Rough, !- Roughness + 0.0095, !- Thickness {m} + 0.16, !- Conductivity {W/m-K} + 1120, !- Density {kg/m3} + 1460, !- Specific Heat {J/kg-K} + 0.9, !- Absorptance:Thermal + 0.7; !- Absorptance:Solar + + Material, + G01 13mm gypsum board, !- Name + Smooth, !- Roughness + 0.0127, !- Thickness {m} + 0.1600, !- Conductivity {W/m-K} + 800.0000, !- Density {kg/m3} + 1090.0000, !- Specific Heat {J/kg-K} + 0.9000, !- Absorptance:Thermal + 0.7000, !- Absorptance:Solar + 0.5000; !- Absorptance:Visible + + Material, + G01 16mm gypsum board, !- Name + MediumSmooth, !- Roughness + 0.0159, !- Thickness {m} + 0.16, !- Conductivity {W/m-K} + 800, !- Density {kg/m3} + 1090; !- Specific Heat {J/kg-K} + + Material, + G02 16mm plywood, !- Name + Smooth, !- Roughness + 0.0159, !- Thickness {m} + 0.12, !- Conductivity {W/m-K} + 544, !- Density {kg/m3} + 1210; !- Specific Heat {J/kg-K} + + Material, + M14 150mm heavyweight concrete roof, !- Name + MediumRough, !- Roughness + 0.1524, !- Thickness {m} + 2.31, !- Conductivity {W/m-K} + 2322, !- Density {kg/m3} + 832; !- Specific Heat {J/kg-K} + + + Material, + 100mm Normalweight concrete wall, !- Name - based on 90.1-2004 Appendix-Table A3-1B + MediumRough, !- Roughness + 0.1016, !- Thickness {m} + 2.31, !- Conductivity {W/m-K} + 2322, !- Density {kg/m3} + 832; !- Specific Heat {J/kg-K} + + + Material, + 200mm Normalweight concrete wall, !- Name - based on 90.1-2004 Appendix-Table A3-1B + MediumRough, !- Roughness + 0.2032, !- Thickness {m} + 2.31, !- Conductivity {W/m-K} + 2322, !- Density {kg/m3} + 832; !- Specific Heat {J/kg-K} + + Material, + 100mm Normalweight concrete floor, !- Name - based on 90.1-2004 Appendix-Table A3-1B + MediumRough, !- Roughness + 0.1016, !- Thickness {m} + 2.31, !- Conductivity {W/m-K} + 2322, !- Density {kg/m3} + 832; !- Specific Heat {J/kg-K} + + Material, + 150mm Normalweight concrete floor, !- Name - based on 90.1-2004 Appendix-Table A3-1B + MediumRough, !- Roughness + 0.1524, !- Thickness {m} + 2.31, !- Conductivity {W/m-K} + 2322, !- Density {kg/m3} + 832; !- Specific Heat {J/kg-K} + + Material, + 200mm Normalweight concrete floor, !- Name - based on 90.1-2004 Appendix-Table A3-1B + MediumRough, !- Roughness + 0.2032, !- Thickness {m} + 2.31, !- Conductivity {W/m-K} + 2322, !- Density {kg/m3} + 832; !- Specific Heat {J/kg-K} + + Material, + M10 200mm concrete block wall, !- Name + MediumRough, !- Roughness + 0.2032, !- Thickness {m} + 0.72, !- Conductivity {W/m-K} + 800, !- Density {kg/m3} + 832; !- Specific Heat {J/kg-K} + + Material, + M10 200mm concrete block basement wall, !- Name + MediumRough, !- Roughness + 0.2032, !- Thickness {m} + 1.326, !- Conductivity {W/m-K} + 1842, !- Density {kg/m3} + 912; !- Specific Heat {J/kg-K} + + + +!- =========== ALL OBJECTS IN CLASS: MATERIAL:REGULAR-R =========== +! Name +! Roughness +! Thermal Resistance +! Absorptance:Thermal -- +! Absorptance:Solar + + + Material:NoMass, + Air_Wall_Material, !- Name + Rough, !- Roughness + 0.2079491, !- Thermal Resistance {m2-K/W} + 0.9, !- Thermal Absorptance + 0.7; !- Solar Absorptance + + + Material:NoMass, + Nonres_Roof_Insulation, !- Name + MediumSmooth, !- Roughness + 0.0299387330245182, + !- Thermal Resistance {m2-K/W} + 0.9, !- Absorptance:Thermal + 0.7, !- Absorptance:Solar + 0.7; !- Absorptance:Visible + + Material:NoMass, + Res_Roof_Insulation, !- Name + MediumSmooth, !- Roughness + 3.47220376108688, + !- Thermal Resistance {m2-K/W} + 0.9, !- Thermal Absorptance + 0.7, !- Solar Absorptance + 0.7; !- Visible Absorptance + + Material:NoMass, + Res_Roof_Insulation_post2013, !- Name + MediumSmooth, !- Roughness + 5.30668495131472, + !- Thermal Resistance {m2-K/W} + 0.9, !- Thermal Absorptance + 0.7, !- Solar Absorptance + 0.7; !- Visible Absorptance + + Material:NoMass, + Semiheated_Roof_Insulation, !- Name + MediumSmooth, !- Roughness + 0.0299387330245182, + !- Thermal Resistance {m2-K/W} + 0.9, !- Thermal Absorptance + 0.7, !- Solar Absorptance + 0.7; !- Visible Absorptance + + + + Material:NoMass, + Nonres_Exterior_Wall_Insulation, !- Name + MediumSmooth, !- Roughness + 0.0299387330245182, + !- Thermal Resistance {m2-K/W} + 0.9, !- Thermal Absorptance + 0.7, !- Solar Absorptance + 0.7; !- Visible Absorptance + + Material:NoMass, + Res_Exterior_Wall_Insulation, !- Name + MediumSmooth, !- Roughness + 2.36800034244138, + !- Thermal Resistance {m2-K/W} + 0.9, !- Thermal Absorptance + 0.7, !- Solar Absorptance + 0.7; !- Visible Absorptance + + Material:NoMass, + Semiheated_Exterior_Wall_Insulation, !- Name + MediumSmooth, !- Roughness + 0.0299387330245182, + !- Thermal Resistance {m2-K/W} + 0.9, !- Thermal Absorptance + 0.7, !- Solar Absorptance + 0.7; !- Visible Absorptance + + + + Material:NoMass, + Nonres_Floor_Insulation, !- Name + MediumSmooth, !- Roughness + + 0.0299387330245182, + !- Thermal Resistance {m2-K/W} + 0.9, !- Thermal Absorptance + 0.7, !- Solar Absorptance + 0.7; !- Visible Absorptance + + Material:NoMass, + Res_Floor_Insulation, !- Name + MediumSmooth, !- Roughness + + 0.0299387330245182, + !- Thermal Resistance {m2-K/W} + 0.9, !- Thermal Absorptance + 0.7, !- Solar Absorptance + 0.7; !- Visible Absorptance + + Material:NoMass, + Semiheated_Floor_Insulation, !- Name + MediumSmooth, !- Roughness + + 0.0299387330245182, + !- Thermal Resistance {m2-K/W} + 0.9, !- Thermal Absorptance + 0.7, !- Solar Absorptance + 0.7; !- Visible Absorptance + +!- Door material properties taken from DOE Benchmark files released in Nov. 2008 + + Material:NoMass, + Std Opaque Door Panel, !- Name + MediumRough, !- Roughness + 0.123456790123457, !- (corresponds to default RSI-0.12327 or R-0.7) Thermal Resistance {m2-K/W} + 0.9, !- Thermal Absorptance + 0.7, !- Solar Absorptance + 0.7; !- Visible Absorptance + +!- =========== ALL OBJECTS IN CLASS: CONSTRUCTION =========== + + Construction, + Air_Wall, !- Name + Air_Wall_Material; !- Outside Layer + + Construction, + DropCeiling, !- Name + AC02 Acoustic Ceiling; !- Outside Layer + + Construction, + OpaqueDoor, !- Name + Std Opaque Door Panel; !- Outside Layer + + Construction, + AtticRoofDeck, !- Name + F12 Asphalt shingles, !- Outside Layer + G02 16mm plywood; !- Layer 2 + + Construction, + int_wall, !- Name + G01 13mm gypsum board, !- Outside Layer + G01 13mm gypsum board; !- Layer 2 + + Construction, + ext_slab_8in_with_carpet,!- Name + 200mm Normalweight concrete floor, !- Outside Layer + CP02 CARPET PAD; !- Layer 2 + + Construction, + ext_slab_8in, !- Name + 200mm Normalweight concrete floor; !- Outside Layer + + Construction, + ext_slab_6in_with_carpet,!- Name + 150mm Normalweight concrete floor, !- Outside Layer + CP02 CARPET PAD; !- Layer 2 + + Construction, + ext_slab_6in, !- Name + 150mm Normalweight concrete floor; !- Outside Layer + + Construction, + int_slab_floor, !- Name + 100mm Normalweight concrete floor, !- Outside Layer + CP02 CARPET PAD; !- Layer 2 + + Construction, + int_slab_ceiling, !- Name + CP02 CARPET PAD, !- Outside Layer + 100mm Normalweight concrete floor; !- Layer 2 + + Construction, + basement_wall, !- Name + M10 200mm concrete block basement wall; !- Outside Layer + + Construction, + int_wood_floor, !- Name + AC02 Acoustic Ceiling, !- Outside Layer + G02 16mm plywood, !- Layer 2 + CP02 CARPET PAD; !- Layer 3 + + Construction, + ext_soffit_floor, !- Name + G02 16mm plywood; !- Outside Layer + + Construction, + nonres_roof, !- Name + F13 Built-up roofing, !- Outside Layer + Nonres_Roof_Insulation, !- Layer #2 + F08 Metal surface; !- Layer #3 + + + Construction, + res_roof, !- Name + F13 Built-up roofing, !- Outside Layer + Res_Roof_Insulation, !- Layer #2 + F08 Metal surface; !- Layer #3 + + Construction, + res_roof_post2013, !- Name + F13 Built-up roofing, !- Outside Layer + Res_Roof_Insulation_post2013, !- Layer #2 + F08 Metal surface; !- Layer #3 + + Construction, + semiheated_roof, !- Name + F13 Built-up roofing, !- Outside Layer + Semiheated_Roof_Insulation, !- Layer #2 + F08 Metal surface; !- Layer #3 + + + + + Construction, + nonres_ext_wall, !- Name + F07 25mm stucco, !- Outside Layer + G01 16mm gypsum board, !- Layer #2 + Nonres_Exterior_Wall_Insulation, !- Layer #3 + G01 16mm gypsum board; !- Layer #4 + + + Construction, + res_ext_wall, !- Name + F07 25mm stucco, !- Outside Layer + G01 16mm gypsum board, !- Layer #1 + Res_Exterior_Wall_Insulation, !- Layer #2 + G01 16mm gypsum board; !- Layer #3 + + + Construction, + semiheated_ext_wall, !- Name + F07 25mm stucco, !- Outside Layer + G01 16mm gypsum board, !- Layer #1 + Semiheated_Exterior_Wall_Insulation, !- Layer #2 + G01 16mm gypsum board; !- Layer #3 + + + Construction, + nonres_floor, !- Name + Nonres_Floor_Insulation, !- Outside Layer + 100mm Normalweight concrete floor, !- Layer #1 + CP02 CARPET PAD; !- Layer #2 + + + Construction, + res_floor, !- Name + Res_Floor_Insulation, !- Outside Layer + 100mm Normalweight concrete floor, !- Layer #1 + CP02 CARPET PAD; !- Layer #2 + + + Construction, + semiheated_floor, !- Name + Semiheated_Floor_Insulation, !- Outside Layer + 100mm Normalweight concrete floor, !- Layer #1 + CP02 CARPET PAD; !- Layer #2 + + + Construction, + nonres_floor_ceiling, !- Name - reverse ordered layers for nonres_floor + CP02 CARPET PAD, !- Outside Layer + 100mm Normalweight concrete floor, !- Layer #1 + Nonres_Floor_Insulation; !- Layer #2 + + Construction, + res_floor_ceiling, !- Name - reverse ordered layers for res_floor + CP02 CARPET PAD, !- Outside Layer + 100mm Normalweight concrete floor, !- Layer #1 + Res_Floor_Insulation; !- Layer #2 + + Construction, + semiheated_floor_ceiling, !- Name - reverse ordered layers for semiheated_floor + CP02 CARPET PAD, !- Outside Layer + 100mm Normalweight concrete floor, !- Layer #1 + Semiheated_Floor_Insulation; !- Layer #2 + + + + + + + +!- =========== ALL OBJECTS IN CLASS: MATERIAL:WINDOWGLASS =========== +! ------------------------------------------------------------------ +! $Id: WindowsLibrary_v30.idf,v 1.6 2010/10/16 00:03:25 atha577 Exp $ +! $Log: WindowsLibrary_v30.idf,v $ +! Revision 1.6 2010/10/16 00:03:25 atha577 +! Deleted bb skylight constructions. Added them to opaquelibraryscript. +! +! Revision 1.5 2010/10/15 23:31:07 atha577 +! Added addendum bb skylight constructions. +! +! Revision 1.4 2010/10/14 22:53:47 atha577 +! Added new skylight constructions for bb +! +! Revision 1.3 2010/05/19 20:10:16 atha577 +! *** empty log message *** +! +! Revision 1.2 2010/05/19 20:08:49 atha577 +! added bb constructions. +! +! +! Revision 1.1 2010/01/20 21:58:41 d3l143 +! Initial revision +! Revised 5/19/2010: Added new constructions for bb from E+ window +! construction library +! +! ------------------------------------------------------------------ +! +!- =========== ALL OBJECTS IN CLASS: MATERIAL:WINDOWGLASS =========== + + WindowMaterial:Glazing, + GREEN 6MM, !- Name + SpectralAverage, !- Optical Data Type + , !- Window Glass Spectral Data Set Name + 0.006, !- Thickness {m} + 0.487, !- Solar Transmittance at Normal Incidence + 0.056, !- Front Side Solar Reflectance at Normal Incidence + 0.056, !- Back Side Solar Reflectance at Normal Incidence + 0.749, !- Visible Transmittance at Normal Incidence + 0.070, !- Front Side Visible Reflectance at Normal Incidence + 0.070, !- Back Side Visible Reflectance at Normal Incidence + 0.0, !- Infrared Transmittance at Normal Incidence + 0.84, !- Front Side Infrared Hemispherical Emissivity + 0.84, !- Back Side Infrared Hemispherical Emissivity + 0.9; !- Conductivity {W/m-K} + +! ID 221 + + WindowMaterial:Glazing, + REF B CLEAR HI 6MM, !- Name + SpectralAverage, !- Optical Data Type + , !- Window Glass Spectral Data Set Name + 0.006, !- Thickness {m} + 0.240, !- Solar Transmittance at Normal Incidence + 0.160, !- Front Side Solar Reflectance at Normal Incidence + 0.320, !- Back Side Solar Reflectance at Normal Incidence + 0.300, !- Visible Transmittance at Normal Incidence + 0.160, !- Front Side Visible Reflectance at Normal Incidence + 0.290, !- Back Side Visible Reflectance at Normal Incidence + 0.0, !- Infrared Transmittance at Normal Incidence + 0.84, !- Front Side Infrared Hemispherical Emissivity + 0.60, !- Back Side Infrared Hemispherical Emissivity + 0.9; !- Conductivity {W/m-K} + + WindowMaterial:Glazing, + REF C CLEAR HI 6MM, !- Name + SpectralAverage, !- Optical Data Type + , !- Window Glass Spectral Data Set Name + 0.006, !- Thickness {m} + 0.200, !- Solar Transmittance at Normal Incidence + 0.160, !- Front Side Solar Reflectance at Normal Incidence + 0.390, !- Back Side Solar Reflectance at Normal Incidence + 0.220, !- Visible Transmittance at Normal Incidence + 0.170, !- Front Side Visible Reflectance at Normal Incidence + 0.350, !- Back Side Visible Reflectance at Normal Incidence + 0.0, !- Infrared Transmittance at Normal Incidence + 0.84, !- Front Side Infrared Hemispherical Emissivity + 0.55, !- Back Side Infrared Hemispherical Emissivity + 0.9; !- Conductivity {W/m-K} + + WindowMaterial:Glazing, + ECREF-1 COLORED 6MM, !- Name + SpectralAverage, !- Optical Data Type + , !- Window Glass Spectral Data Set Name + 0.006, !- Thickness {m} + 0.099, !- Solar Transmittance at Normal Incidence + 0.219, !- Front Side Solar Reflectance at Normal Incidence + 0.219, !- Back Side Solar Reflectance at Normal Incidence + 0.155, !- Visible Transmittance at Normal Incidence + 0.073, !- Front Side Visible Reflectance at Normal Incidence + 0.073, !- Back Side Visible Reflectance at Normal Incidence + 0.0, !- Infrared Transmittance at Normal Incidence + 0.84, !- Front Side Infrared Hemispherical Emissivity + 0.84, !- Back Side Infrared Hemispherical Emissivity + 0.9; !- Conductivity {W/m-K} + + WindowMaterial:Glazing, + REF B TINT MID 6MM, !- Name + SpectralAverage, !- Optical Data Type + , !- Window Glass Spectral Data Set Name + 0.006, !- Thickness {m} + 0.100, !- Solar Transmittance at Normal Incidence + 0.110, !- Front Side Solar Reflectance at Normal Incidence + 0.410, !- Back Side Solar Reflectance at Normal Incidence + 0.130, !- Visible Transmittance at Normal Incidence + 0.100, !- Front Side Visible Reflectance at Normal Incidence + 0.320, !- Back Side Visible Reflectance at Normal Incidence + 0.0, !- Infrared Transmittance at Normal Incidence + 0.84, !- Front Side Infrared Hemispherical Emissivity + 0.45, !- Back Side Infrared Hemispherical Emissivity + 0.9; !- Conductivity {W/m-K} + + WindowMaterial:Glazing, + CLEAR 6MM, !- Name + SpectralAverage, !- Optical Data Type + , !- Window Glass Spectral Data Set Name + 0.006, !- Thickness {m} + 0.775, !- Solar Transmittance at Normal Incidence + 0.071, !- Front Side Solar Reflectance at Normal Incidence + 0.071, !- Back Side Solar Reflectance at Normal Incidence + 0.881, !- Visible Transmittance at Normal Incidence + 0.080, !- Front Side Visible Reflectance at Normal Incidence + 0.080, !- Back Side Visible Reflectance at Normal Incidence + 0.0, !- Infrared Transmittance at Normal Incidence + 0.84, !- Front Side Infrared Hemispherical Emissivity + 0.84, !- Back Side Infrared Hemispherical Emissivity + 0.9; !- Conductivity {W/m-K} + + WindowMaterial:Glazing, + REF D CLEAR 6MM, !- Name + SpectralAverage, !- Optical Data Type + , !- Window Glass Spectral Data Set Name + 0.006, !- Thickness {m} + 0.429, !- Solar Transmittance at Normal Incidence + 0.308, !- Front Side Solar Reflectance at Normal Incidence + 0.379, !- Back Side Solar Reflectance at Normal Incidence + 0.334, !- Visible Transmittance at Normal Incidence + 0.453, !- Front Side Visible Reflectance at Normal Incidence + 0.505, !- Back Side Visible Reflectance at Normal Incidence + 0.0, !- Infrared Transmittance at Normal Incidence + 0.84, !- Front Side Infrared Hemispherical Emissivity + 0.82, !- Back Side Infrared Hemispherical Emissivity + 0.9; !- Conductivity {W/m-K} + + WindowMaterial:Glazing, + BLUE 6MM, !- Name + SpectralAverage, !- Optical Data Type + , !- Window Glass Spectral Data Set Name + 0.006, !- Thickness {m} + 0.480, !- Solar Transmittance at Normal Incidence + 0.050, !- Front Side Solar Reflectance at Normal Incidence + 0.050, !- Back Side Solar Reflectance at Normal Incidence + 0.570, !- Visible Transmittance at Normal Incidence + 0.060, !- Front Side Visible Reflectance at Normal Incidence + 0.060, !- Back Side Visible Reflectance at Normal Incidence + 0.0, !- Infrared Transmittance at Normal Incidence + 0.84, !- Front Side Infrared Hemispherical Emissivity + 0.84, !- Back Side Infrared Hemispherical Emissivity + 0.9; !- Conductivity {W/m-K} + + WindowMaterial:Glazing, + GREY 6MM, !- Name + SpectralAverage, !- Optical Data Type + , !- Window Glass Spectral Data Set Name + 0.006, !- Thickness {m} + 0.455, !- Solar Transmittance at Normal Incidence + 0.053, !- Front Side Solar Reflectance at Normal Incidence + 0.053, !- Back Side Solar Reflectance at Normal Incidence + 0.431, !- Visible Transmittance at Normal Incidence + 0.052, !- Front Side Visible Reflectance at Normal Incidence + 0.052, !- Back Side Visible Reflectance at Normal Incidence + 0.0, !- Infrared Transmittance at Normal Incidence + 0.84, !- Front Side Infrared Hemispherical Emissivity + 0.84, !- Back Side Infrared Hemispherical Emissivity + 0.9; !- Conductivity {W/m-K} + + WindowMaterial:Glazing, + LoE CLEAR 6MM, !- Name + SpectralAverage, !- Optical Data Type + , !- Window Glass Spectral Data Set Name + 0.006, !- Thickness {m} + 0.600, !- Solar Transmittance at Normal Incidence + 0.170, !- Front Side Solar Reflectance at Normal Incidence + 0.220, !- Back Side Solar Reflectance at Normal Incidence + 0.840, !- Visible Transmittance at Normal Incidence + 0.055, !- Front Side Visible Reflectance at Normal Incidence + 0.078, !- Back Side Visible Reflectance at Normal Incidence + 0.0, !- Infrared Transmittance at Normal Incidence + 0.84, !- Front Side Infrared Hemispherical Emissivity + 0.10, !- Back Side Infrared Hemispherical Emissivity + 0.9; !- Conductivity {W/m-K} + +WindowMaterial:Glazing,LoE TINT 6MM,SpectralAverage, ,.006,.360,.093,.200,.500,.035,.054,.0,.84,.10,.9; ! ID 451 +WindowMaterial:Glazing,REF B TINT HI 6MM,SpectralAverage, ,.006,.150,.090,.330,.180,.080,.280,.0,.84,.60,.9; ! ID 232 +WindowMaterial:Glazing,REF C CLEAR MID 6MM,SpectralAverage, ,.006,.170,.200,.420,.190,.210,.380,.0,.84,.51,.9; ! ID 241 + +WindowMaterial:Glazing,REF D TINT 6MM,SpectralAverage, ,.006,.300,.140,.360,.250,.180,.450,.0,.84,.82,.9; ! ID 270 +WindowMaterial:Glazing,COATED POLY-77,SpectralAverage, ,.00051,.504,.402,.398,.766,.147,.167,.0,.075,.720,.14; ! ID 601 +WindowMaterial:Glazing,LoE SPEC SEL TINT 6MM,SpectralAverage, ,.006,.260,.140,.410,.460,.060,.040,.0,.84,.03,.9; ! ID 550 + +WindowMaterial:Glazing,PYR B CLEAR 6MM,SpectralAverage, ,.006,.680,.090,.100,.810,.110,.120,.0,.84,.20,.9; ! ID 351 + +WindowMaterial:Glazing,REF B CLEAR LO 6MM,SpectralAverage, ,.006,.150,.220,.380,.200,.230,.330,.0,.84,.58,.9; ! ID 220 +WindowMaterial:Glazing,REF A CLEAR LO 6MM,SpectralAverage, ,.006,.066,.341,.493,.080,.410,.370,.0,.84,.40,.9; ! ID 200 +WindowMaterial:Glazing,GREEN 3MM,SpectralAverage, ,.003,.635,.063,.063,.822,.075,.075,.0,.84,.84,.9; ! ID 11 +WindowMaterial:Glazing,ECABS-2 COLORED 6MM,SpectralAverage, ,.006,.111,.179,.179,.128,.081,.081,.0,.84,.10,.9; ! ID 705 +WindowMaterial:Glazing,COATED POLY-55,SpectralAverage, ,.00051,.320,.582,.593,.551,.336,.375,.0,.046,.720,.14; ! ID 603 +WindowMaterial:Glazing,ECREF-2 COLORED 6MM,SpectralAverage, ,.006,.099,.219,.219,.155,.073,.073,.0,.84,.10,.9; ! ID 707 +WindowMaterial:Glazing,LoE SPEC SEL CLEAR 6MM Rev,SpectralAverage,,.006,.430,.420,.300,.770,.060,.070,.0,.03,.84,.9; ! +WindowMaterial:Glazing,BRONZE 6MM,SpectralAverage, ,.006,.482,.054,.054,.534,.057,.057,.0,.84,.84,.9; ! ID 6 +WindowMaterial:Glazing,REF A TINT MID 6MM,SpectralAverage, ,.006,.060,.130,.420,.090,.140,.350,.0,.84,.47,.9; ! ID 211 + + +WindowMaterial:Glazing, + Theoretical Glass 297, !- Name + SpectralAverage, !- Optical Data Type + , !- Window Glass Spectral Data Set Name + 0.003, !- Thickness {m} + 0.375039, !- Solar Transmittance at Normal Incidence + 0.574961, !- Front Side Solar Reflectance at Normal Incidence + 0.574961, !- Back Side Solar Reflectance at Normal Incidence + 0.529698, !- Visible Transmittance at Normal Incidence + 0.420302, !- Front Side Visible Reflectance at Normal Incidence + 0.420302, !- Back Side Visible Reflectance at Normal Incidence + 0, !- Infrared Transmittance at Normal Incidence + 0.9, !- Front Side Infrared Hemispherical Emissivity + 0.9, !- Back Side Infrared Hemispherical Emissivity + 0.0103561; !- Conductivity {W/m-K} + +WindowMaterial:Glazing, + Theoretical Glass 347, !- Name + SpectralAverage, !- Optical Data Type + , !- Window Glass Spectral Data Set Name + 0.003, !- Thickness {m} + 0.315861, !- Solar Transmittance at Normal Incidence + 0.634139, !- Front Side Solar Reflectance at Normal Incidence + 0.634139, !- Back Side Solar Reflectance at Normal Incidence + 0.479911, !- Visible Transmittance at Normal Incidence + 0.470089, !- Front Side Visible Reflectance at Normal Incidence + 0.470089, !- Back Side Visible Reflectance at Normal Incidence + 0, !- Infrared Transmittance at Normal Incidence + 0.9, !- Front Side Infrared Hemispherical Emissivity + 0.9, !- Back Side Infrared Hemispherical Emissivity + 0.010358; !- Conductivity {W/m-K} + + +!- =========== ALL OBJECTS IN CLASS: MATERIAL:WINDOWGAS =========== + + WindowMaterial:Gas, + AIR 6MM, !- Name + Air, !- Gas Type + 0.0063; !- Thickness {m} + + WindowMaterial:Gas, + AIR 13MM, !- Name + Air, !- Gas Type + 0.0127; !- Thickness {m} + + WindowMaterial:Gas, + ARGON 13MM, !- Name + Argon, !- Gas Type + 0.0127; !- Thickness {m} + +!- =========== ALL OBJECTS IN CLASS: CONSTRUCTION =========== +! Sgl Green 6mm, !- Name + + Construction, + Window_U_1.22_SHGC_0.61, !- Name + GREEN 6MM; !- Outside Layer + +! Sgl Ref-B-H Clr 6mm, !- Name + + Construction, + Window_U_1.22_SHGC_0.39, !- Name + REF B CLEAR HI 6MM; !- Outside Layer + +! Sgl Ref-C-H Clr 6mm, !- Name + + Construction, + Window_U_1.22_SHGC_0.34, !- Name + REF C CLEAR HI 6MM; !- Outside Layer + +! Sgl Elec Ref Colored 6mm,!- Name + + Construction, + Window_U_1.22_SHGC_0.25, !- Name + ECREF-1 COLORED 6MM; !- Outside Layer + +! Sgl Ref-B-M Tint 6mm, !- Name + + Construction, + Window_U_0.72_SHGC_0.25, !- Name + REF B TINT MID 6MM; !- Outside Layer + +! Dbl Ref-D Clr 6mm/6mm Air, !- Name + + Construction, + Window_U_0.62_SHGC_0.39, !- Name + REF D CLEAR 6MM, !- Outside Layer + AIR 6MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl Ref-D Clr 6mm/6mm Air, !- Name + + Construction, + Window_U_0.57_SHGC_0.39, !- Name + REF D CLEAR 6MM, !- Outside Layer + AIR 6MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl Ref-C-H Clr 6mm/6mm Air, !- Name + + Construction, + Window_U_0.65_SHGC_0.25, !- Name + REF C CLEAR HI 6MM, !- Outside Layer + AIR 6MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl Ref-C-H Clr 6mm/6mm Air, !- Name + + Construction, + Window_U_0.62_SHGC_0.25, !- Name + REF C CLEAR HI 6MM, !- Outside Layer + AIR 6MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl Ref-C-H Clr 6mm/6mm Air, !- Name + + Construction, + Window_U_0.57_SHGC_0.25, !- Name + REF C CLEAR HI 6MM, !- Outside Layer + AIR 6MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl Blue 6mm/6mm Air, !- Name + + Construction, + Window_U_0.62_SHGC_0.49, !- Name + BLUE 6MM, !- Outside Layer + AIR 6MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl Blue 6mm/6mm Air, !- Name + + Construction, + Window_U_0.57_SHGC_0.49, !- Name + BLUE 6MM, !- Outside Layer + AIR 6MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl Ref-D Clr 6mm/13mm Air, !- Name + + Construction, + Window_U_0.52_SHGC_0.40, !- Name + REF D CLEAR 6MM, !- Outside Layer + AIR 13MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl Ref-D Clr 6mm/13mm Air, !- Name + + Construction, + Window_U_0.48_SHGC_0.40, !- Name + REF D CLEAR 6MM, !- Outside Layer + AIR 13MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl Ref-D Clr 6mm/13mm Arg, !- Name + + Construction, + Window_U_0.42_SHGC_0.45, !- Name + REF D CLEAR 6MM, !- Outside Layer + ARGON 13MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl Grey 6mm/13mm Air, !- Name + + Construction, + Window_U_0.46_SHGC_0.45, !- Name + GREY 6MM, !- Outside Layer + AIR 13MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl LoE (e2=.1) Tint 6mm/6mm Air, !- Name + + Construction, + Window_U_0.42_SHGC_0.40, !- Name + LoE TINT 6MM, !- Outside Layer + AIR 6MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl Ref-B-H Clr 6mm/13mm Air, !- Name + +Construction, + Window_U_0.43_SHGC_0.26, !- Name + REF B CLEAR HI 6MM, !- Outside Layer + AIR 13MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl Ref-B-H Clr 6mm/13mm Air, !- Name + +Construction, + Window_U_0.44_SHGC_0.26, !- Name + REF B CLEAR HI 6MM, !- Outside Layer + AIR 13MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl LoE (e2=.1) Tint 6mm/6mm Air, !- Name + +Construction, + Window_U_0.42_SHGC_0.35, !- Name + LoE TINT 6MM, !- Outside Layer + AIR 6MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl LoE (e2=.1) Tint 6mm/13mm Air, !- Name + +Construction, + Window_U_0.33_SHGC_0.40, !- Name + LoE TINT 6MM, !- Outside Layer + AIR 13MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +Construction, + Window_U_0.34_SHGC_0.40, !- Name + LoE TINT 6MM, !- Outside Layer + AIR 13MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl LoE (e2=.1) Tint 6mm/13mm Air, !- Name + +Construction, + Window_U_0.35_SHGC_0.35, !- Name + LoE TINT 6MM, !- Outside Layer + AIR 13MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl Ref-D Tint 6mm/6mm Air, !- Name + +Construction, + Window_U_0.55_SHGC_0.31, !- Name + REF D TINT 6MM, !- Outside Layer + AIR 6MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl LoE Spec Sel Tint 6mm/6mm Air, !- Name + +Construction, + Window_U_0.43_SHGC_0.29, !- Name + LoE SPEC SEL TINT 6MM, !- Outside Layer + AIR 6MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl LoE (e2=.2) Clr 6mm/13mm Air, !- Name + +Construction, + Window_U_0.34_SHGC_0.45, !- Name + PYR B CLEAR 6MM, !- Outside Layer + AIR 13MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl Ref-D Tint 6mm/6mm Air, !- Name + +Construction, + Window_U_0.56_SHGC_0.35, !- Name + REF D TINT 6MM, !- Outside Layer + AIR 6MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl Ref-B-H Clr 6mm/13mm Air, !- Name (0.44/0.30) + +Construction, + Window_U_0.45_SHGC_0.31, !- Name + REF B CLEAR HI 6MM, !- Outside Layer + AIR 13MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Trp LoE Film (77) Clr 3mm/6mm Air, !- Name (0.31/0.46) + +Construction, + Window_U_0.33_SHGC_0.45, !- Name + CLEAR 3MM, !- Outside Layer + AIR 6MM, !- Layer 2 + COATED POLY-77, !- Layer 3 + AIR 6MM, !- Layer 4 + CLEAR 3MM; !- Layer 5 + +! Dbl Ref B-H Tint 6mm/13mm Arg, ! U=2.297 SC= .27 SHGC=.236 TSOL=.119 TVIS=.163 + +Construction, + Window_U_0.38_SHGC_0.26, !- Name + REF B TINT HI 6MM, + ARGON 13MM, + CLEAR 6MM; + +! Dbl LoE (e2=.1) Tint 6mm/13mm Arg, ! U=1.502 SC= .43 SHGC=.371 TSOL=.284 TVIS=.444 + +Construction, + Window_U_0.25_SHGC_0.40, !- Name + LoE TINT 6MM, + ARGON 13MM, + CLEAR 6MM; + +! Dbl Ref-C-M Clr 6mm/13mm Arg, ! U=2.184 SC= .27 SHGC=.233 TSOL=.136 TVIS=.173 + +Construction, + Window_U_0.35_SHGC_0.26, !- Name + REF C CLEAR MID 6MM, + ARGON 13MM, + CLEAR 6MM; + + +! Dbl Ref-C-H Clr 6mm/6mm Air, !- Name + +Construction, + Window_U_0.54_SHGC_0.27, !- Name + REF C CLEAR HI 6MM, !- Outside Layer + AIR 6MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl Ref-A-M Tint 6mm/6mm Air, !- Name + +Construction, + Window_U_0.54_SHGC_0.18, !- Name + REF A TINT MID 6MM, !- Outside Layer + AIR 6MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl Ref-A-L Clr 6mm/13mm Air, !- Name + +Construction, + Window_U_0.54_SHGC_0.13, !- Name + REF A CLEAR LO 6MM, !- Outside Layer + AIR 13MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl LoE Elec Ref Colored 6mm/13mm Air, !- Name + +Construction, + Window_U_0.33_SHGC_0.11, !- Name + ECREF-2 COLORED 6MM, !- Outside Layer + AIR 13MM, !- Layer 2 + LoE SPEC SEL CLEAR 6MM Rev; !- Layer 3 + +! Trp LoE Film (55) Bronze 6mm/6mm Air, !- Name + +Construction, + Window_U_0.29_SHGC_0.22, !- Name + BRONZE 6MM, !- Outside Layer + AIR 6MM, !- Layer 2 + COATED POLY-55, !- Layer 3 + AIR 6MM, !- Layer 4 + CLEAR 6MM; !- Layer 5 + +! Dbl Elec Abs Colored 6mm/13mm Air, !- Name + +Construction, + Window_U_0.29_SHGC_0.17, !- Name + ECABS-2 COLORED 6MM, !- Outside Layer + AIR 13MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl LoE Elec Ref Colored 6mm/13mm Air, !- Name + +Construction, + Window_U_0.29_SHGC_0.11, !- Name + ECREF-2 COLORED 6MM, !- Outside Layer + AIR 13MM, !- Layer 2 + LoE SPEC SEL CLEAR 6MM Rev; !- Layer 3 + + +! Dbl LoE Spec Sel Tint 6mm/13mm Arg, !- Name + +Construction, + Window_U_0.24_SHGC_0.23, !- Name + LoE SPEC SEL TINT 6MM, !- Outside Layer + ARGON 13MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl Elec Abs Colored 6mm/13mm Arg, !- Name + +Construction, + Window_U_0.24_SHGC_0.16, !- Name + ECABS-2 COLORED 6MM, !- Outside Layer + ARGON 13MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + + +! Dbl LoE Elec Abs Colored 6mm/13mm Arg, !- Name + +Construction, + Window_U_0.24_SHGC_0.11, !- Name + ECABS-2 COLORED 6MM, !- Outside Layer + ARGON 13MM, !- Layer 2 + LoE SPEC SEL CLEAR 6MM Rev; !- Layer 3 + + +! Trp LoE Film (55) Bronze 6mm/13mm Air, !- Name + +Construction, + Window_U_0.19_SHGC_0.20, !- Name + BRONZE 6MM, !- Outside Layer + AIR 13MM, !- Layer 2 + COATED POLY-55, !- Layer 3 + AIR 13MM, !- Layer 4 + CLEAR 6MM; !- Layer 5 + + +! +! +! Following constructions are added as part of Addendum bb +! +! + +! Dbl Ref-C-H Clr 6mm/6mm Air + +Construction, + Window_U_0.71_SHGC_0.25, !- Name + REF C CLEAR HI 6MM, !- Outside Layer + AIR 6MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + + +! Dbl Ref-B-H Clr 6mm/13mm Arg + +Construction, + Window_U_0.38_SHGC_0.30, !- Name + REF B CLEAR HI 6MM, !- Outside Layer + ARGON 13MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + + +! Dbl LoE Spec Sel Tint 6mm/6mm Air + +Construction, + Window_U_0.36_SHGC_0.35, !- Name + LoE SPEC SEL TINT 6MM, !- Outside Layer + AIR 6MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + + +! Dbl LoE (e2=.1) Tint 6mm/13mm Air + +Construction, + Window_U_0.30_SHGC_0.40, !- Name + LoE TINT 6MM, !- Outside Layer + AIR 13MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + + +! +! +! End set of new bb constructions +! +! + + + + +!=================skylight==================== + +! Sgl Ref-B-H Clr 6mm, !- Name + + Construction, + Window_U_1.98_SHGC_0.36, !- Name + REF B CLEAR HI 6MM; !- Outside Layer + +! Sgl Ref-B-H Clr 6mm, !- Name + + Construction, + Window_U_1.17_SHGC_0.39, !- Name + REF B CLEAR HI 6MM; !- Outside Layer + +! Sgl Green 6mm, !- Name + + Construction, + Window_U_1.98_SHGC_0.61, !- Name + GREEN 6MM; !- Outside Layer + +! Sgl Ref-D Clr 6mm, !- Name + + Construction, + Window_U_1.17_SHGC_0.49, !- Name + REF D CLEAR 6MM; !- Outside Layer + +! Sgl Green 3mm, !- Name + + Construction, + Window_U_1.17_SHGC_0.68, !- Name + GREEN 3MM; !- Outside Layer + +! Sgl Ref-B-H Clr 6mm, !- Name + + Construction, + Window_U_0.98_SHGC_0.45, !- Name + REF B CLEAR HI 6MM; !- Outside Layer + +! Sgl Ref-B-H Clr 6mm, !- Name + + Construction, + Window_U_0.98_SHGC_0.68, !- Name + REF B CLEAR HI 6MM; !- Outside Layer + +! Sgl Ref-A-L Clr 6mm, !- Name + + Construction, + Window_U_0.88_SHGC_0.16, !- Name + REF A CLEAR LO 6MM; !- Outside Layer + +! Sgl Elec Ref Colored 6mm,!- Name + + Construction, + Window_U_0.88_SHGC_0.27, !- Name + ECREF-1 COLORED 6MM; !- Outside Layer + +! Dbl Ref-B-L Clr 6mm/6mm Air, !- Name + + Construction, + Window_U_0.52_SHGC_0.22, !- Name + REF B CLEAR LO 6MM, !- Outside Layer + AIR 6MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +! Dbl Ref-B-H Tint 6mm/13mm Air, !- Name + + Construction, + Window_U_0.44_SHGC_0.20, !- Name + REF B TINT HI 6MM, !- Outside Layer + AIR 13MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + + +Construction, + Window_U_0.39_SHGC_0.38, !- Name + Theoretical Glass 297; !- Outside Layer + +Construction, + Window_U_0.39_SHGC_0.32, !- Name + Theoretical Glass 347; !- Outside Layer + +!=================Additional Skylight Constructions for 189.1==================== + +! Sgl LoE (e2=.2) Clr 6mm, !- Name + +Construction, + Window_U_0.75_SHGC_0.72, !- Name + PYR B CLEAR 6MM; !- Outside Layer + +! Sgl LoE (e2=.2) Clr 3mm, !- Name + +Construction, + Window_U_0.67_SHGC_0.77, !- Name + PYR B CLEAR 3MM; !- Outside Layer + +! Dbl Clr 3mm/6mm Air, !- Name + +Construction, + Window_U_0.56_SHGC_0.76, !- Name + CLEAR 3MM, !- Outside Layer + AIR 6MM, !- Layer 2 + CLEAR 3MM; !- Layer 3 + +WindowMaterial:Glazing,PYR B CLEAR 3MM,SpectralAverage, ,.003,.740,.090,.100,.820,.110,.120,.0,.84,.20,.9; ! ID 350 + + +!=================Additional Window Constructions for 189.1==================== + +! Dbl LoE Spec Sel Clr 3mm/6mm/6mm Air, !- Name + +Construction, + Window_U_0.40_SHGC_0.43, !- Name + LoE SPEC SEL CLEAR 3MM, !- Outside Layer + AIR 6MM, !- Layer 2 + CLEAR 6MM; !- Layer 3 + +WindowMaterial:Glazing,LoE SPEC SEL CLEAR 3MM,SpectralAverage, ,.003,.450,.340,.370,.780,.070,.060,.0,.84,.03,.9; ! ID 500 + +!=================Additional Window Materials and Constructions for 50% Concept==================== + + +WindowMaterial:Glazing,ECABS-2 BLEACHED 6MM,SpectralAverage, ,.006,.814,.086,.086,.847,.099,.099,.0,.84,.10,.9; ! ID 704 + +! Dbl LoE Elec Abs Bleached 6mm/6mm Air, !- Name + +Construction, + Window_U_0.40_SHGC_0.45, !- Name + ECABS-2 BLEACHED 6MM, !- Outside Layer + AIR 6MM, !- Layer 2 + LoE SPEC SEL CLEAR 6MM Rev; !- Layer 3 + +! +! The next four constructions are derived from Window 6.3. +! Refer to the scorecard for individual layers' definitions. +! + +WindowMaterial:Glazing, +Glass_2175_LayerAvg, !- Layer name : GREY-SGP-E366 - 8.6.CIG +SpectralAverage, !- Optical Data Type +, !- Spectral Data name +0.008600, !- Thickness +0.167758, !- Solar Transmittance +2.176064e-001, !- Solar Front Reflectance +4.379779e-001, !- Solar Back Reflectance +0.416044, !- Visible Transmittance +0.078729, !-Visible Front Reflectance +0.106540, !-Visible Back reflectance +0.000000, !- IR Transmittance +0.840000, !-Front Emissivity +0.840000, !-Back Emissivity +1; !-Conductivity + + +WindowMaterial:Glazing, +Glass_2022F_LayerAvg, !- Layer name : LoE262-4.CIG +SpectralAverage, !- Optical Data Type +, !- Spectral Data name +0.003900, !- Thickness +0.355897, !- Solar Transmittance +3.940945e-001, !- Solar Front Reflectance +2.656452e-001, !- Solar Back Reflectance +0.677694, !- Visible Transmittance +0.042734, !- Visible Front Reflectance +0.055470, !- Visible Back reflectance +0.000000, !- IR Transmittance +0.046000, !-Front Emissivity +0.840000, !-Back Emissivity +1; !-Conductivity + +WindowMaterial:Glazing, +Glass_2052_LayerAvg, !- Layer name : 86SGP-G.CIG +SpectralAverage, !- Optical Data Type +, !- Spectral Data name +0.008370, !- Thickness +0.507767, !- Solar Transmittance +5.422805e-002, !- Solar Front Reflectance +5.449309e-002, !- Solar Back Reflectance +0.586833, !- Visible Transmittance +0.058050, !-Visible Front Reflectance +0.058397, !-Visible Back reflectance +0.000000, !- IR Transmittance +0.840000, !-Front Emissivity +0.840000, !-Back Emissivity +1; !-Conductivity + + +WindowMaterial:Glazing, +Glass_2010F_LayerAvg, !- Layer name : LoE272-2.CIG +SpectralAverage, !- Optical Data Type +, !- Spectral Data name +0.002210, !- Thickness +0.434294, !- Solar Transmittance +4.183747e-001, !- Solar Front Reflectance +3.410654e-001, !- Solar Back Reflectance +0.797579, !- Visible Transmittance +0.043577, !- Visible Front Reflectance +0.056031, !- Visible Back reflectance +0.000000, !- IR Transmittance +0.042274, !-Front Emissivity +0.840000, !-Back Emissivity +1; !-Conductivity + +WindowMaterial:Glazing, +Glass_2027F_LayerAvg, !- Layer name : LoE270-4.CIG +SpectralAverage, !- Optical Data Type +, !- Spectral Data name +0.004000, !- Thickness +0.369744, !- Solar Transmittance +4.700695e-001, !- Solar Front Reflectance +3.409350e-001, !- Solar Back Reflectance +0.765222, !- Visible Transmittance +0.054600, !- Visible Front Reflectance +0.073741, !- Visible Back reflectance +0.000000, !- IR Transmittance +0.036750, !-Front Emissivity +0.840000, !-Back Emissivity +1; !-Conductivity + + +WindowMaterial:Gas, +Gap_1_W_0_0025, !- gap name - Air +Air, !- type +0.0025; !- thickness + +WindowMaterial:Gas, +Gap_1_W_0_0032, !- gap name - Air +Air, !- type +0.0032; !- thickness + +WindowMaterial:Gas, +Gap_1_W_0_0042, !- gap name - Air +Air, !- type +0.0042; !- thickness + +WindowMaterial:Gas, +Gap_1_W_0_0043, !- gap name - Air +Air, !- type +0.0043; !- thickness + +WindowMaterial:Gas, +Gap_1_W_0_0018, !- gap name - Air +Air, !- type +0.0018; !- thickness + +WindowMaterial:Gas, +Gap_1_W_0_0024, !- gap name - Air +Air, !- type +0.0024; !- thickness + +WindowMaterial:Gas, +Gap_1_W_0_0038, !- gap name - Air +Air, !- type +0.0038; !- thickness + + + +Construction, + Window_U_0.60_SHGC_0.25, !- Name + Glass_2175_LayerAvg, !- glass name : GREY-SGP-E366 - 8.6.CIG + Gap_1_W_0_0025, !- gap name - Air + Glass_2022F_LayerAvg; !- glass name : LoE262-4.CIG + + +Construction, + Window_U_0.55_SHGC_0.25, !- Name + Glass_2175_LayerAvg, !- glass name : GREY-SGP-E366 - 8.6.CIG + Gap_1_W_0_0032, !- gap name - Air + Glass_2022F_LayerAvg; !- glass name : LoE262-4.CIG + + +Construction, + Window_U_0.50_SHGC_0.25, !- Name + Glass_2175_LayerAvg, !- glass name : GREY-SGP-E366 - 8.6.CIG + Gap_1_W_0_0042, !- gap name - Air + Glass_2022F_LayerAvg; !- glass name : LoE262-4.CIG + + +Construction, + Window_U_0.47_SHGC_0.40, !- Name + Glass_2052_LayerAvg, !- glass name : 86SGP-G.CIG + Gap_1_W_0_0043, !- gap name - Air + Glass_2010F_LayerAvg; !- glass name : LoE272-2.CIG + + + + + +!=================Additional Skylight Materials and Constructions for 50% Concept==================== + +! +! The next four constructions are derived from Window 6.3. +! Refer to the scorecard for individual layers. +! + + +Construction, + Window_U_0.75_SHGC_0.35, !- Name + Glass_2052_LayerAvg, !- glass name : 86SGP-G.CIG + Gap_1_W_0_0018, !- gap name - Air + Glass_2027F_LayerAvg; !- glass name : LoE270-4.CIG + + +Construction, + Window_U_0.65_SHGC_0.35, !- Name + Glass_2052_LayerAvg, !- glass name : 86SGP-G.CIG + Gap_1_W_0_0024, !- gap name - Air + Glass_2027F_LayerAvg; !- glass name : LoE270-4.CIG + + +Construction, + Window_U_0.55_SHGC_0.35, !- Name + Glass_2052_LayerAvg, !- glass name : 86SGP-G.CIG + Gap_1_W_0_0038, !- gap name - Air + Glass_2027F_LayerAvg; !- glass name : LoE270-4.CIG + + +Construction, + Window_U_0.50_SHGC_0.40, !- Name + Glass_2052_LayerAvg, !- glass name : 86SGP-G.CIG + Gap_1_W_0_0038, !- gap name - Air + Glass_2027F_LayerAvg; !- glass name : LoE270-4.CIG + +!=================Additional Windows for IECC Analysis================================================ + + +!Sgl Elec Ref Colored 6mm +Construction, + Window_U_1.16_SHGC_0.25, !- Name + ECREF-1 COLORED 6MM; !- glass name + +! Sgl Elec Ref Colored 6mm +Construction, + Window_U_1.08_SHGC_0.25, !- Name + ECREF-1 COLORED 6MM; !- glass name + +! Dbl Elec Ref Bleached 6mm/13mm Air, !- Name + +WindowMaterial:Glazing,ECREF-2 BLEACHED 6MM,SpectralAverage, ,.006,.694,.168,.168,.818,.110,.110,.0,.84,.10,.9; ! ID 706 + +Construction, + Window_U_0.29_SHGC_0.45, !- Name + ECREF-2 BLEACHED 6MM, !- Outside Layer + AIR 13MM, !- Layer 2 + LoE SPEC SEL CLEAR 6MM Rev; !- Layer 3 + + + +!=================Additional Skylights for IECC Analysis================================================ + +! Using Window_U_0.65_SHGC_0.35 and Window_U_0.75_SHGC_0.35 from 50% concepts. + +!Sgl Ref-B-H Clr 6mm, Add frame width and frame conductivity +! Glazing Properties- Assembly U factor = 0.89, SHGC = 0.4. This includes the effect of air films. +! Skylight frame has ben added with the following properties- +! Frame width = 0.7129; Frame conductivity = 283.91 + +Construction, + Window_U_1.60_SHGC_0.40, !- Name + REF B CLEAR HI 6MM; !- glass name + +! Sgl Ref-C-H Clr 6mm, Add frame width and frame conductivity +! Glazing Properties- Assembly U factor = 0.89, SHGC = 0.4. This includes the effect of air films. +! Skylight frame has ben added with the following properties- +! Frame width = 0.1271; Frame conductivity = 283.91 + +Construction, + Window_U_1.05_SHGC_0.40, !- Name + REF B CLEAR HI 6MM; !- glass name + +! Sgl Ref-C-H Clr 6mm, Add frame width and frame conductivity +! Same construction (Assembly U factor = 0.89, SHGC = 0.4) has been used with frame width = 0. +Construction, + Window_U_0.90_SHGC_0.40, !- Name + REF B CLEAR HI 6MM; !- glass name + +! ================================================================================ +! ASHRAE 189.1 2009 Construction Library + +Material, + F08 Metal surface, !- Name + Smooth, !- Roughness + 0.0008, !- Thickness {m} + 45.2800000000001, !- Conductivity {W/m-K} + 7823.99999999999, !- Density {kg/m3} + 500, !- Specific Heat {J/kg-K} + 0.9, !- Thermal Absorptance + 0.7, !- Solar Absorptance + 0.7; !- Visible Absorptance + +Material, + F16 Acoustic tile, !- Name + MediumSmooth, !- Roughness + 0.0191, !- Thickness {m} + 0.06, !- Conductivity {W/m-K} + 368, !- Density {kg/m3} + 590.000000000002, !- Specific Heat {J/kg-K} + 0.9, !- Thermal Absorptance + 0.3, !- Solar Absorptance + 0.3; !- Visible Absorptance + +Material, + G01a 19mm gypsum board, !- Name + MediumSmooth, !- Roughness + 0.019, !- Thickness {m} + 0.16, !- Conductivity {W/m-K} + 800, !- Density {kg/m3} + 1090, !- Specific Heat {J/kg-K} + 0.9, !- Thermal Absorptance + 0.4, !- Solar Absorptance + 0.4; !- Visible Absorptance + +Material, + G05 25mm wood, !- Name + MediumSmooth, !- Roughness + 0.0254, !- Thickness {m} + 0.15, !- Conductivity {W/m-K} + 608, !- Density {kg/m3} + 1630, !- Specific Heat {J/kg-K} + 0.9, !- Thermal Absorptance + 0.5, !- Solar Absorptance + 0.5; !- Visible Absorptance + +Material, + I01 25mm insulation board, !- Name + MediumRough, !- Roughness + 0.0254, !- Thickness {m} + 0.03, !- Conductivity {W/m-K} + 43, !- Density {kg/m3} + 1210, !- Specific Heat {J/kg-K} + 0.9, !- Thermal Absorptance + 0.6, !- Solar Absorptance + 0.6; !- Visible Absorptance + +Material, + M11 100mm lightweight concrete, !- Name + MediumRough, !- Roughness + 0.1016, !- Thickness {m} + 0.53, !- Conductivity {W/m-K} + 1280, !- Density {kg/m3} + 840.000000000002, !- Specific Heat {J/kg-K} + 0.9, !- Thermal Absorptance + 0.5, !- Solar Absorptance + 0.5; !- Visible Absorptance + +Material, + Roof Insulation [18], !- Name + MediumRough, !- Roughness + 0.1693, !- Thickness {m} + 0.049, !- Conductivity {W/m-K} + 265, !- Density {kg/m3} + 836.800000000001, !- Specific Heat {J/kg-K} + 0.9, !- Thermal Absorptance + 0.7, !- Solar Absorptance + 0.7; !- Visible Absorptance + +Material, + Roof Insulation [21], !- Name + MediumRough, !- Roughness + 0.2105, !- Thickness {m} + 0.049, !- Conductivity {W/m-K} + 265, !- Density {kg/m3} + 836.800000000001, !- Specific Heat {J/kg-K} + 0.9, !- Thermal Absorptance + 0.7, !- Solar Absorptance + 0.7; !- Visible Absorptance + +Material, + Roof Insulation [25], !- Name + MediumRough, !- Roughness + 0.263, !- Thickness {m} + 0.049, !- Conductivity {W/m-K} + 265, !- Density {kg/m3} + 836.800000000001, !- Specific Heat {J/kg-K} + 0.9, !- Thermal Absorptance + 0.7, !- Solar Absorptance + 0.7; !- Visible Absorptance + +Material, + Roof Insulation [26], !- Name + MediumRough, !- Roughness + 0.2941, !- Thickness {m} + 0.049, !- Conductivity {W/m-K} + 265, !- Density {kg/m3} + 836.800000000001, !- Specific Heat {J/kg-K} + 0.9, !- Thermal Absorptance + 0.7, !- Solar Absorptance + 0.7; !- Visible Absorptance + +Material, + Wall Insulation [31], !- Name + MediumRough, !- Roughness + 0.0337000000000001, !- Thickness {m} + 0.0432, !- Conductivity {W/m-K} + 91, !- Density {kg/m3} + 836.999999999999, !- Specific Heat {J/kg-K} + 0.9, !- Thermal Absorptance + 0.5, !- Solar Absorptance + 0.5; !- Visible Absorptance + +Material, + Wall Insulation [35], !- Name + MediumRough, !- Roughness + 0.0452, !- Thickness {m} + 0.0432, !- Conductivity {W/m-K} + 91, !- Density {kg/m3} + 836.999999999999, !- Specific Heat {J/kg-K} + 0.9, !- Thermal Absorptance + 0.5, !- Solar Absorptance + 0.5; !- Visible Absorptance + +Material, + Wall Insulation [36], !- Name + MediumRough, !- Roughness + 0.0565999999999999, !- Thickness {m} + 0.0432, !- Conductivity {W/m-K} + 91, !- Density {kg/m3} + 836.999999999999, !- Specific Heat {J/kg-K} + 0.9, !- Thermal Absorptance + 0.5, !- Solar Absorptance + 0.5; !- Visible Absorptance + +Material, + Wall Insulation [37], !- Name + MediumRough, !- Roughness + 0.0680999999999999, !- Thickness {m} + 0.0432, !- Conductivity {W/m-K} + 91, !- Density {kg/m3} + 836.999999999999, !- Specific Heat {J/kg-K} + 0.9, !- Thermal Absorptance + 0.5, !- Solar Absorptance + 0.5; !- Visible Absorptance + +Material, + Wall Insulation [40], !- Name + MediumRough, !- Roughness + 0.0793999999999999, !- Thickness {m} + 0.0432, !- Conductivity {W/m-K} + 91, !- Density {kg/m3} + 836.999999999999, !- Specific Heat {J/kg-K} + 0.9, !- Thermal Absorptance + 0.5, !- Solar Absorptance + 0.5; !- Visible Absorptance + +Material, + Wall Insulation [42], !- Name + MediumRough, !- Roughness + 0.0913999999999999, !- Thickness {m} + 0.0432, !- Conductivity {W/m-K} + 91, !- Density {kg/m3} + 836.999999999999, !- Specific Heat {J/kg-K} + 0.9, !- Thermal Absorptance + 0.5, !- Solar Absorptance + 0.5; !- Visible Absorptance + +Material, + Wall Insulation [44], !- Name + MediumRough, !- Roughness + 0.1104, !- Thickness {m} + 0.0432, !- Conductivity {W/m-K} + 91, !- Density {kg/m3} + 836.999999999999, !- Specific Heat {J/kg-K} + 0.9, !- Thermal Absorptance + 0.5, !- Solar Absorptance + 0.5; !- Visible Absorptance + +Material:AirGap, + F04 Wall air space resistance, !- Name + 0.15; !- Thermal Resistance {m2-K/W} + +Material:AirGap, + F05 Ceiling air space resistance, !- Name + 0.18; !- Thermal Resistance {m2-K/W} + +Material, + Air Wall Material, !- Name + MediumSmooth, !- Roughness + 0.01, !- Thickness {m} + 0.6, !- Conductivity {W/m-K} + 800, !- Density {kg/m3} + 1000, !- Specific Heat {J/kg-K} + 0.95, !- Thermal Absorptance + 0.7, !- Solar Absorptance + 0.7; !- Visible Absorptance + +WindowMaterial:Glazing, + Clear 3mm, !- Name + SpectralAverage, !- Optical Data Type + , !- Window Glass Spectral Data Set Name + 0.00299999999999999, !- Thickness {m} + 0.837, !- Solar Transmittance at Normal Incidence + 0.075, !- Front Side Solar Reflectance at Normal Incidence + 0, !- Back Side Solar Reflectance at Normal Incidence + 0.898, !- Visible Transmittance at Normal Incidence + 0.081, !- Front Side Visible Reflectance at Normal Incidence + 0, !- Back Side Visible Reflectance at Normal Incidence + 0, !- Infrared Transmittance at Normal Incidence + 0.84, !- Front Side Infrared Hemispherical Emissivity + 0.84, !- Back Side Infrared Hemispherical Emissivity + 0.9, !- Conductivity {W/m-K} + 1, !- Dirt Correction Factor for Solar and Visible Transmittance + No; !- Solar Diffusing + +WindowMaterial:Glazing, + Theoretical Glass [167], !- Name + SpectralAverage, !- Optical Data Type + , !- Window Glass Spectral Data Set Name + 0.00299999999999999, !- Thickness {m} + 0.2374, !- Solar Transmittance at Normal Incidence + 0.7126, !- Front Side Solar Reflectance at Normal Incidence + 0, !- Back Side Solar Reflectance at Normal Incidence + 0.2512, !- Visible Transmittance at Normal Incidence + 0.6988, !- Front Side Visible Reflectance at Normal Incidence + 0, !- Back Side Visible Reflectance at Normal Incidence + 0, !- Infrared Transmittance at Normal Incidence + 0.985, !- Front Side Infrared Hemispherical Emissivity + 0.985, !- Back Side Infrared Hemispherical Emissivity + 2.1073, !- Conductivity {W/m-K} + 1, !- Dirt Correction Factor for Solar and Visible Transmittance + No; !- Solar Diffusing + +WindowMaterial:Glazing, + Theoretical Glass [197], !- Name + SpectralAverage, !- Optical Data Type + , !- Window Glass Spectral Data Set Name + 0.00299999999999999, !- Thickness {m} + 0.2349, !- Solar Transmittance at Normal Incidence + 0.7151, !- Front Side Solar Reflectance at Normal Incidence + 0, !- Back Side Solar Reflectance at Normal Incidence + 0.2512, !- Visible Transmittance at Normal Incidence + 0.6988, !- Front Side Visible Reflectance at Normal Incidence + 0, !- Back Side Visible Reflectance at Normal Incidence + 0, !- Infrared Transmittance at Normal Incidence + 0.9, !- Front Side Infrared Hemispherical Emissivity + 0.9, !- Back Side Infrared Hemispherical Emissivity + 0.0415, !- Conductivity {W/m-K} + 1, !- Dirt Correction Factor for Solar and Visible Transmittance + No; !- Solar Diffusing + +WindowMaterial:Glazing, + Theoretical Glass [202], !- Name + SpectralAverage, !- Optical Data Type + , !- Window Glass Spectral Data Set Name + 0.00299999999999999, !- Thickness {m} + 0.2325, !- Solar Transmittance at Normal Incidence + 0.7175, !- Front Side Solar Reflectance at Normal Incidence + 0, !- Back Side Solar Reflectance at Normal Incidence + 0.3192, !- Visible Transmittance at Normal Incidence + 0.6308, !- Front Side Visible Reflectance at Normal Incidence + 0, !- Back Side Visible Reflectance at Normal Incidence + 0, !- Infrared Transmittance at Normal Incidence + 0.9, !- Front Side Infrared Hemispherical Emissivity + 0.9, !- Back Side Infrared Hemispherical Emissivity + 0.0192, !- Conductivity {W/m-K} + 1, !- Dirt Correction Factor for Solar and Visible Transmittance + No; !- Solar Diffusing + +WindowMaterial:Glazing, + Theoretical Glass [207], !- Name + SpectralAverage, !- Optical Data Type + , !- Window Glass Spectral Data Set Name + 0.00299999999999999, !- Thickness {m} + 0.3311, !- Solar Transmittance at Normal Incidence + 0.6189, !- Front Side Solar Reflectance at Normal Incidence + 0, !- Back Side Solar Reflectance at Normal Incidence + 0.44, !- Visible Transmittance at Normal Incidence + 0.51, !- Front Side Visible Reflectance at Normal Incidence + 0, !- Back Side Visible Reflectance at Normal Incidence + 0, !- Infrared Transmittance at Normal Incidence + 0.9, !- Front Side Infrared Hemispherical Emissivity + 0.9, !- Back Side Infrared Hemispherical Emissivity + 0.0133, !- Conductivity {W/m-K} + 1, !- Dirt Correction Factor for Solar and Visible Transmittance + No; !- Solar Diffusing + +WindowMaterial:Glazing, + Theoretical Glass [216], !- Name + SpectralAverage, !- Optical Data Type + , !- Window Glass Spectral Data Set Name + 0.00299999999999999, !- Thickness {m} + 0.3801, !- Solar Transmittance at Normal Incidence + 0.5699, !- Front Side Solar Reflectance at Normal Incidence + 0, !- Back Side Solar Reflectance at Normal Incidence + 0.5079, !- Visible Transmittance at Normal Incidence + 0.4421, !- Front Side Visible Reflectance at Normal Incidence + 0, !- Back Side Visible Reflectance at Normal Incidence + 0, !- Infrared Transmittance at Normal Incidence + 0.9, !- Front Side Infrared Hemispherical Emissivity + 0.9, !- Back Side Infrared Hemispherical Emissivity + 0.0133, !- Conductivity {W/m-K} + 1, !- Dirt Correction Factor for Solar and Visible Transmittance + No; !- Solar Diffusing + +WindowMaterial:Glazing, + Theoretical Glass [221], !- Name + SpectralAverage, !- Optical Data Type + , !- Window Glass Spectral Data Set Name + 0.00299999999999999, !- Thickness {m} + 0.4296, !- Solar Transmittance at Normal Incidence + 0.5204, !- Front Side Solar Reflectance at Normal Incidence + 0, !- Back Side Solar Reflectance at Normal Incidence + 0.4503, !- Visible Transmittance at Normal Incidence + 0.4997, !- Front Side Visible Reflectance at Normal Incidence + 0, !- Back Side Visible Reflectance at Normal Incidence + 0, !- Infrared Transmittance at Normal Incidence + 0.9, !- Front Side Infrared Hemispherical Emissivity + 0.9, !- Back Side Infrared Hemispherical Emissivity + 0.0089, !- Conductivity {W/m-K} + 1, !- Dirt Correction Factor for Solar and Visible Transmittance + No; !- Solar Diffusing + +Construction, + Air Wall, !- Name + Air Wall Material; !- Layer 1 + +Construction, + ASHRAE 189.1-2009 ExtRoof IEAD ClimateZone 1, !- Name + Roof Membrane, !- Layer 1 + Roof Insulation [18], !- Layer 2 + Metal Decking; !- Layer 3 + +Construction, + ASHRAE 189.1-2009 ExtRoof IEAD ClimateZone 2-5, !- Name + Roof Membrane, !- Layer 1 + Roof Insulation [21], !- Layer 2 + Metal Decking; !- Layer 3 + +Construction, + ASHRAE 189.1-2009 ExtRoof IEAD ClimateZone 7-8, !- Name + Roof Membrane, !- Layer 1 + Roof Insulation [26], !- Layer 2 + Metal Decking; !- Layer 3 + +Construction, + ASHRAE 189.1-2009 ExtRoof Metal ClimateZone 6, !- Name + Metal Roofing, !- Layer 1 + Roof Insulation [25], !- Layer 2 + Metal Decking; !- Layer 3 + +Construction, + ASHRAE 189.1-2009 ExtWall Mass ClimateZone 1, !- Name + 1IN Stucco, !- Layer 1 + 8IN Concrete HW, !- Layer 2 + Wall Insulation [31], !- Layer 3 + 1/2IN Gypsum; !- Layer 4 + +Construction, + ASHRAE 189.1-2009 ExtWall Mass ClimateZone 2, !- Name + 1IN Stucco, !- Layer 1 + 8IN Concrete HW, !- Layer 2 + Wall Insulation [35], !- Layer 3 + 1/2IN Gypsum; !- Layer 4 + +Construction, + ASHRAE 189.1-2009 ExtWall Mass ClimateZone 3, !- Name + 1IN Stucco, !- Layer 1 + 8IN Concrete HW, !- Layer 2 + Wall Insulation [36], !- Layer 3 + 1/2IN Gypsum; !- Layer 4 + +Construction, + ASHRAE 189.1-2009 ExtWall Mass ClimateZone 4, !- Name + 1IN Stucco, !- Layer 1 + 8IN Concrete HW, !- Layer 2 + Wall Insulation [37], !- Layer 3 + 1/2IN Gypsum; !- Layer 4 + +Construction, + ASHRAE 189.1-2009 ExtWall Mass ClimateZone 5, !- Name + 1IN Stucco, !- Layer 1 + 8IN Concrete HW, !- Layer 2 + Wall Insulation [40], !- Layer 3 + 1/2IN Gypsum; !- Layer 4 + +Construction, + ASHRAE 189.1-2009 ExtWall Mass ClimateZone 6, !- Name + 1IN Stucco, !- Layer 1 + 8IN Concrete HW, !- Layer 2 + Wall Insulation [42], !- Layer 3 + 1/2IN Gypsum; !- Layer 4 + +Construction, + ASHRAE 189.1-2009 ExtWall Mass ClimateZone 7-8, !- Name + 1IN Stucco, !- Layer 1 + 8IN Concrete HW, !- Layer 2 + Wall Insulation [44], !- Layer 3 + 1/2IN Gypsum; !- Layer 4 + +Construction, + ASHRAE 189.1-2009 ExtWindow ClimateZone 1, !- Name + Theoretical Glass [167]; !- Layer 1 + +Construction, + ASHRAE 189.1-2009 ExtWindow ClimateZone 2, !- Name + Theoretical Glass [197]; !- Layer 1 + +Construction, + ASHRAE 189.1-2009 ExtWindow ClimateZone 3, !- Name + Theoretical Glass [202]; !- Layer 1 + +Construction, + ASHRAE 189.1-2009 ExtWindow ClimateZone 4-5, !- Name + Theoretical Glass [207]; !- Layer 1 + +Construction, + ASHRAE 189.1-2009 ExtWindow ClimateZone 6, !- Name + Theoretical Glass [216]; !- Layer 1 + +Construction, + ASHRAE 189.1-2009 ExtWindow ClimateZone 7-8, !- Name + Theoretical Glass [221]; !- Layer 1 + +Construction, + Exterior Door, !- Name + F08 Metal surface, !- Layer 1 + I01 25mm insulation board; !- Layer 2 + +Construction, + ExtSlabCarpet 4in ClimateZone 1-8, !- Name + MAT-CC05 4 HW CONCRETE, !- Layer 1 + CP02 CARPET PAD; !- Layer 2 + +Construction, + Interior Ceiling, !- Name + M11 100mm lightweight concrete, !- Layer 1 + F05 Ceiling air space resistance, !- Layer 2 + F16 Acoustic tile; !- Layer 3 + +Construction, + Interior Door, !- Name + G05 25mm wood; !- Layer 1 + +Construction, + Interior Floor, !- Name + F16 Acoustic tile, !- Layer 1 + F05 Ceiling air space resistance, !- Layer 2 + M11 100mm lightweight concrete; !- Layer 3 + +Construction, + Interior Partition, !- Name + G05 25mm wood; !- Layer 1 + +Construction, + Interior Wall, !- Name + G01a 19mm gypsum board, !- Layer 1 + F04 Wall air space resistance, !- Layer 2 + G01a 19mm gypsum board; !- Layer 3 + +Construction, + Interior Window, !- Name + Clear 3mm; !- Layer 1 + diff --git a/bpeng/simulation/midrise.py b/bpeng/simulation/midrise.py new file mode 100644 index 0000000..6d7c2ea --- /dev/null +++ b/bpeng/simulation/midrise.py @@ -0,0 +1,763 @@ +import abc +from .base import BaseSim +import math + + +class MidRiseApart(BaseSim): + """ + Class for MidRise Apartment buildings based on energy.gov commercial reference buildings, climate zone 4A + http://energy.gov/eere/buildings/commercial-reference-buildings + """ + # EnergyPlus New IDF Object Database for MidRiseApart + + # Year Schedule + sch_year_new = """Schedule:Year, + , !- Name + , !- Schedule Type Limits Name + , !- Schedule:Week Name 1 + 1, !- Start Month 1 + 1, !- Start Day 1 + 12, !- End Month 1 + 31; !- End Day 1""" + + # Week Schedule + sch_week_new = """Schedule:Week:Daily, + , !- Name + , !- Sunday Schedule:Day Name + , !- Monday Schedule:Day Name + , !- Tuesday Schedule:Day Name + , !- Wednesday Schedule:Day Name + , !- Thursday Schedule:Day Name + , !- Friday Schedule:Day Name + , !- Saturday Schedule:Day Name + , !- Holiday Schedule:Day Name + , !- SummerDesignDay Schedule:Day Name + , !- WinterDesignDay Schedule:Day Name + , !- CustomDay1 Schedule:Day Name + ; !- CustomDay2 Schedule:Day Name""" + + # Daily Occupancy Schedule ("MidriseApartment Apartment Occ Default Schedule" from Open Studio) + sch_occ_d_new = """Schedule:Day:Interval, + , !- Name + , !- Schedule Type Limits Name + No, !- Interpolate to Timestep + 07:00, !- Time 1 {hh:mm} + 1, !- Value Until Time 1 + 08:00, !- Time 2 {hh:mm} + 0.85, !- Value Until Time 2 + 09:00, !- Time 3 {hh:mm} + 0.39, !- Value Until Time 3 + 16:00, !- Time 4 {hh:mm} + 0.25, !- Value Until Time 4 + 17:00, !- Time 5 {hh:mm} + 0.3, !- Value Until Time 5 + 18:00, !- Time 6 {hh:mm} + 0.52, !- Value Until Time 6 + 21:00, !- Time 7 {hh:mm} + 0.87, !- Value Until Time 7 + 24:00, !- Time 8 {hh:mm} + 1; !- Value Until Time 8""" + + # Daily Activity Schedule ("MidriseApartment Activity Default Schedule" from Open Studio) + sch_act_d_new = """Schedule:Day:Interval, + , !- Name + , !- Schedule Type Limits Name + No, !- Interpolate to Timestep + 24:00, !- Time 1 {hh:mm} + 120; !- Value Until Time 1""" + + # Daily Equipment Schedule ("MidriseApartment Apartment Equip Default Schedule" from Open Studio) + sch_equip_d_new = """Schedule:Day:Interval, + , !- Name + , !- Schedule Type Limits Name + No, !- Interpolate to Timestep + 01:00, !- Time 1 {hh:mm} + 0.45, !- Value Until Time 1 + 02:00, !- Time 2 {hh:mm} + 0.41, !- Value Until Time 2 + 03:00, !- Time 3 {hh:mm} + 0.39, !- Value Until Time 3 + 05:00, !- Time 4 {hh:mm} + 0.38, !- Value Until Time 4 + 06:00, !- Time 5 {hh:mm} + 0.43, !- Value Until Time 5 + 07:00, !- Time 6 {hh:mm} + 0.54, !- Value Until Time 6 + 08:00, !- Time 7 {hh:mm} + 0.65, !- Value Until Time 7 + 09:00, !- Time 8 {hh:mm} + 0.66, !- Value Until Time 8 + 10:00, !- Time 9 {hh:mm} + 0.67, !- Value Until Time 9 + 11:00, !- Time 10 {hh:mm} + 0.69, !- Value Until Time 10 + 12:00, !- Time 11 {hh:mm} + 0.7, !- Value Until Time 11 + 13:00, !- Time 12 {hh:mm} + 0.69, !- Value Until Time 12 + 14:00, !- Time 13 {hh:mm} + 0.66, !- Value Until Time 13 + 15:00, !- Time 14 {hh:mm} + 0.65, !- Value Until Time 14 + 16:00, !- Time 15 {hh:mm} + 0.68, !- Value Until Time 15 + 17:00, !- Time 16 {hh:mm} + 0.8, !- Value Until Time 16 + 19:00, !- Time 17 {hh:mm} + 1, !- Value Until Time 17 + 20:00, !- Time 18 {hh:mm} + 0.93, !- Value Until Time 18 + 21:00, !- Time 19 {hh:mm} + 0.89, !- Value Until Time 19 + 22:00, !- Time 20 {hh:mm} + 0.85, !- Value Until Time 20 + 23:00, !- Time 21 {hh:mm} + 0.71, !- Value Until Time 21 + 24:00, !- Time 22 {hh:mm} + 0.58; !- Value Until Time 22""" + + # Daily Light Schedule ("MidriseApartment Apartment Light Default Schedule" from Open Studio) + sch_light_d_new = """Schedule:Day:Interval, + , !- Name + , !- Schedule Type Limits Name + No, !- Interpolate to Timestep + 04:00, !- Time 1 {hh:mm} + 0.067, !- Value Until Time 1 + 05:00, !- Time 2 {hh:mm} + 0.187, !- Value Until Time 2 + 06:00, !- Time 3 {hh:mm} + 0.394, !- Value Until Time 3 + 07:00, !- Time 4 {hh:mm} + 0.44, !- Value Until Time 4 + 08:00, !- Time 5 {hh:mm} + 0.393, !- Value Until Time 5 + 09:00, !- Time 6 {hh:mm} + 0.172, !- Value Until Time 6 + 15:00, !- Time 7 {hh:mm} + 0.119, !- Value Until Time 7 + 16:00, !- Time 8 {hh:mm} + 0.206, !- Value Until Time 8 + 17:00, !- Time 9 {hh:mm} + 0.439, !- Value Until Time 9 + 18:00, !- Time 10 {hh:mm} + 0.616, !- Value Until Time 10 + 19:00, !- Time 11 {hh:mm} + 0.829, !- Value Until Time 11 + 20:00, !- Time 12 {hh:mm} + 0.986, !- Value Until Time 12 + 21:00, !- Time 13 {hh:mm} + 1, !- Value Until Time 13 + 22:00, !- Time 14 {hh:mm} + 0.692, !- Value Until Time 14 + 23:00, !- Time 15 {hh:mm} + 0.384, !- Value Until Time 15 + 24:00, !- Time 16 {hh:mm} + 0.16; !- Value Until Time 16""" + + # Daily Infiltration Schedule ("MidriseApartment Infil Default Schedule" from Open Studio) + sch_infil_d_new = """Schedule:Day:Interval + , !- Name + , !- Schedule Type Limits Name + No, !- Interpolate to Timestep + 24:00, !- Time 1 {hh:mm} + 1; !- Value Until Time 1""" + + # Occupancy values (ASHRAE 189.1-2009 - MidriseApartment - Apartment - CZ4-8 from Open Studio) + people_apartment_new = """People, + , !- Name + , !- Zone or ZoneList Name + , !- Number of People Schedule Name + People/Area, !- Number of People Calculation Method + , !- Number of People + 0.0283090843959466, !- People per Zone Floor Area {person/m2} + , !- Zone Floor Area per Person {m2/person} + 0.3, !- Fraction Radiant + , !- Sensible Heat Fraction + ; !- Activity Level Schedule Name""" + + # Lighting values for apartment (ASHRAE 90.1 - MidriseApartment - Apartment from Energy.gov) + lights_apartment_new = """Lights, + , !- Name + , !- Zone or ZoneList Name + , !- Schedule Name + Watts/Area, !- Design Level Calculation Method + , !- Lighting Level {W} + 3.88, !- Watts per Zone Floor Area {W/m2} + , !- Watts per Person {W/person} + , !- Return Air Fraction + , !- Fraction Radiant + ; !- Fraction Visible""" + + # Equipment values for apartment (ASHRAE 189.1-2009 - MidriseApartment - Apartment - CZ4-8 from Open Studio) + elecequip_greenbuild_new = """ElectricEquipment, + , !- Name + , !- Zone or ZoneList Name + , !- Schedule Name + Watts/Area, !- Design Level Calculation Method + , !- Design Level {W} + 3.87500941842567, !- Watts per Zone Floor Area {W/m2} + , !- Watts per Person {W/person} + , !- Fraction Latent + , !- Fraction Radiant + ; !- Fraction Lost""" + + # Equipment values for apartment (ASHRAE 90.1 - MidriseApartment - Apartment from Energycodes.gov) + elecequip_apartment_new = """ElectricEquipment, + , !- Name + , !- Zone or ZoneList Name + , !- Schedule Name + Watts/Area, !- Design Level Calculation Method + , !- Design Level {W} + 6.67, !- Watts per Zone Floor Area {W/m2} + , !- Watts per Person {W/person} + 0, !- Fraction Latent + 0.5, !- Fraction Radiant + 0, !- Fraction Lost + General; !- End-Use Subcategory""" + + # Zone infiltration values (ASHRAE 189.1-2009 - MidriseApartment - Apartment - CZ4-8 from Open Studio) + zoneinfil_post2009_new = """ZoneInfiltration:DesignFlowRate, + , !- Name + , !- Zone or ZoneList Name + , !- Schedule Name + Flow/ExteriorArea, !- Design Flow Rate Calculation Method + , !- Design Flow Rate {m3/s} + , !- Flow per Zone Floor Area {m3/s-m2} + 0.000226568, !- Flow per Exterior Surface Area {m3/s-m2} + , !- Air Changes per Hour {1/hr} + , !- Constant Term Coefficient + , !- Temperature Term Coefficient + , !- Velocity Term Coefficient + ; !- Velocity Squared Term Coefficient""" + + # RefBldhMidriseApartmentPre2004 (ASHRAE 90.1-1989 http://energy.gov/eere/buildings/existing-commercial-reference-buildings-constructed-1980) + zoneinfil_pre2004_new = """ZoneInfiltration:DesignFlowRate, + , !- Name + , !- Zone Name + , !- Schedule Name + Flow/ExteriorArea, !- Design Volume Flow Rate Calculation Method + , !- Design Flow Rate {m3/s} + , !- Flow per Zone Area {m3/s/m2} + 0.001133, !- Flow per Exterior Surface Area {m3/s/m2} + , !- Air Changes Per Hour {ACH} + 1.0000, !- Constant Term Coefficient + 0.0000, !- Temperature Term Coefficient + 0.0000, !- Velocity Term Coefficient + 0.0000; !- Velocity Squared Term Coefficient""" + + # RefBldhMidriseApartmentNew2004 (ASHRAE 90.1-2004 http://energy.gov/eere/buildings/new-construction-commercial-reference-buildings) + zoneinfil_post2004_new = """ZoneInfiltration:DesignFlowRate, + , !- Name + , !- Zone Name + , !- Schedule Name + Flow/ExteriorArea, !- Design Volume Flow Rate Calculation Method + , !- Design Flow Rate {m3/s} + , !- Flow per Zone Area {m3/s/m2} + 0.000302, !- Flow per Exterior Surface Area {m3/s/m2} + , !- Air Changes Per Hour {ACH} + 1.0000, !- Constant Term Coefficient + 0.0000, !- Temperature Term Coefficient + 0.0000, !- Velocity Term Coefficient + 0.0000; !- Velocity Squared Term Coefficient""" + + ########################################################## + # Functions + def __init__(self, idf_start_file=None): + super().__init__(idf_start_file=idf_start_file) + + def cons_components(self, cons_year): + """ + Based on age of the building and assuming MidRise Apartment building type, selecting the construction objects + for external wall, ground floor, interior floor, interior ceiling, roof and window constructions from idf file. + + Parameters + ---------- + idf: Oplus IDF object + cons_year: str or int or float + Construction year of the building. + For string input follow the following list: + "pre1980" + "post1980" + "post2004" + "post2007" + "post2010" + "post2013" + "189.1 2009" or "green building 2009" + + Returns + ------- + cons_list: list of IDF construction objects + [cons_wall, cons_groundfloor, cons_intfloor, cons_intceiling, cons_roof, cons_window] + cons_list[0]: external wall construction Oplus IDFObject + cons_list[1]: external ground floor construction Oplus IDFObject + cons_list[2]: interior floor construction Oplus IDFObject + cons_list[3]: interior ceiling construction Oplus IDFObject + cons_list[4]: external roof construction Oplus IDFObject + cons_list[5]: external window construction Oplus IDFObject + """ + if type(cons_year) == int or float: + if cons_year < 1980: + cons_year = "pre1980" + elif 1980 <= cons_year < 2004: + cons_year = "post1980" + elif 2004 <= cons_year < 2007: + cons_year = "post2004" + elif 2007 <= cons_year < 2010: + cons_year = "post2007" + elif 2010 <= cons_year < 2013: + cons_year = "post2010" + elif 2013 <= cons_year: + cons_year = "post2013" + + # pre1980 + if (cons_year == "pre1980"): + cons_wall = self.idf("construction").filter("name", "Steel Frame Res Ext Wall_stucco_pre1980").one + cons_groundfloor = self.idf("construction").filter("name", "ext-slab").one + cons_intfloor = self.idf("construction").filter("name", "INT-FLOOR-TOPSIDE").one + cons_intceiling = self.idf("construction").filter("name", "INT-FLOOR-UNDERSIDE").one + cons_roof = self.idf("construction").filter("name", "IEAD Res Roof_pre1980").one + cons_window = self.idf("construction").filter("name", "Window_U_1.22_SHGC_0.61").one + # post1980 + elif (cons_year == "post1980"): + cons_wall = self.idf("construction").filter("name", "Steel Frame Res Ext Wall_stucco_post1980").one + cons_groundfloor = self.idf("construction").filter("name", "ext-slab").one + cons_intfloor = self.idf("construction").filter("name", "INT-FLOOR-TOPSIDE").one + cons_intceiling = self.idf("construction").filter("name", "INT-FLOOR-UNDERSIDE").one + cons_roof = self.idf("construction").filter("name", "IEAD Res Roof_post1980").one + cons_window = self.idf("construction").filter("name", "Window_U_0.62_SHGC_0.49").one + # post2004 + elif (cons_year == "post2004"): + cons_wall = self.idf("construction").filter("name", "res_ext_wall").one + cons_groundfloor = self.idf("construction").filter("name", "ext_slab_8in_with_carpet").one + cons_intfloor = self.idf("construction").filter("name", "int_slab_floor").one + cons_intceiling = self.idf("construction").filter("name", "int_slab_ceiling").one + cons_roof = self.idf("construction").filter("name", "res_roof").one + cons_window = self.idf("construction").filter("name", "Window_U_0.62_SHGC_0.39").one + # post2007 + elif (cons_year == "post2007"): + cons_wall = self.idf("construction").filter("name", "res_ext_wall").one + cons_groundfloor = self.idf("construction").filter("name", "ext_slab_8in_with_carpet").one + cons_intfloor = self.idf("construction").filter("name", "int_slab_floor").one + cons_intceiling = self.idf("construction").filter("name", "int_slab_ceiling").one + cons_roof = self.idf("construction").filter("name", "res_roof").one + cons_window = self.idf("construction").filter("name", "Window_U_0.52_SHGC_0.40").one + # post2010 + elif (cons_year == "post2010"): + cons_wall = self.idf("construction").filter("name", "res_ext_wall").one + cons_groundfloor = self.idf("construction").filter("name", "ext_slab_8in_with_carpet").one + cons_intfloor = self.idf("construction").filter("name", "int_slab_floor").one + cons_intceiling = self.idf("construction").filter("name", "int_slab_ceiling").one + cons_roof = self.idf("construction").filter("name", "res_roof").one + cons_window = self.idf("construction").filter("name", "Window_U_0.52_SHGC_0.40").one + # post2013 + elif (cons_year == "post2013"): + cons_wall = self.idf("construction").filter("name", "res_ext_wall").one + cons_groundfloor = self.idf("construction").filter("name", "ext_slab_8in_with_carpet").one + cons_intfloor = self.idf("construction").filter("name", "int_slab_floor").one + cons_intceiling = self.idf("construction").filter("name", "int_slab_ceiling").one + cons_roof = self.idf("construction").filter("name", "res_roof_post2013").one + cons_window = self.idf("construction").filter("name", "Window_U_0.42_SHGC_0.40").one + # 189.1 2009 + elif ((cons_year == "189.1 2009") or (cons_year == "green building 2009")): + cons_wall = self.idf("construction").filter("name", "ASHRAE 189.1-2009 ExtWall Mass ClimateZone 4").one + cons_groundfloor = self.idf("construction").filter("name", "ExtSlabCarpet 4in ClimateZone 1-8").one + cons_intfloor = self.idf("construction").filter("name", "Interior Floor").one + cons_intceiling = self.idf("construction").filter("name", "Interior Ceiling").one + cons_roof = self.idf("construction").filter("name", "ASHRAE 189.1-2009 ExtRoof IEAD ClimateZone 2-5").one + cons_window = self.idf("construction").filter("name", "ASHRAE 189.1-2009 ExtWindow ClimateZone 4-5").one + + cons_list = [cons_wall, cons_groundfloor, cons_intfloor, cons_intceiling, cons_roof, cons_window] + + return cons_list + + def sch_infil_add(self, name): + """ + Add IDF schedule object for zone infiltration assuming MidRise Apartment building type + Note that a schedule object will be created for each: + day, summer design day, winter design day, week and year + Only schedule for year is returned + + Parameters + ---------- + idf: Oplus IDF object + name: str + Name assigned to infiltration schedule + + Returns + ------- + sch_infil_year_o: Oplus IDFOject + Schedule:Year for infiltration + """ + fraction = self.idf("ScheduleTypeLimits").filter("name", "Fraction").one + + sch_infil_d_o = self.idf.add_object(sch_infil_d_new) + sch_infil_d_o["name"] = name + " Inf Default Schedule" + sch_infil_d_o["schedule type limits name"] = fraction + + sch_infil_summer_o = self.idf.add_object(sch_infil_d_new) + sch_infil_summer_o["name"] = name + " Inf Summer Design Day" + sch_infil_summer_o["schedule type limits name"] = fraction + + sch_infil_winter_o = self.idf.add_object(sch_infil_d_new) + sch_infil_winter_o["name"] = name + " Inf Winter Design Day" + sch_infil_winter_o["schedule type limits name"] = fraction + + sch_infil_week_o = self.idf.add_object(sch_week_new) + sch_infil_week_o["name"] = name + " Inf Schedule:Week:Daily" + sch_infil_week_o["Sunday Schedule:Day Name"] = sch_infil_d_o + sch_infil_week_o["Monday Schedule:Day Name"] = sch_infil_d_o + sch_infil_week_o["Tuesday Schedule:Day Name"] = sch_infil_d_o + sch_infil_week_o["Wednesday Schedule:Day Name"] = sch_infil_d_o + sch_infil_week_o["Thursday Schedule:Day Name"] = sch_infil_d_o + sch_infil_week_o["Friday Schedule:Day Name"] = sch_infil_d_o + sch_infil_week_o["Saturday Schedule:Day Name"] = sch_infil_d_o + sch_infil_week_o["Holiday Schedule:Day Name"] = sch_infil_d_o + sch_infil_week_o["SummerDesignDay Schedule:Day Name"] = sch_infil_summer_o + sch_infil_week_o["WinterDesignDay Schedule:Day Name"] = sch_infil_winter_o + sch_infil_week_o["CustomDay1 Schedule:Day Name"] = sch_infil_d_o + sch_infil_week_o["CustomDay2 Schedule:Day Name"] = sch_infil_d_o + + sch_infil_year_o = self.idf.add_object(sch_year_new) + sch_infil_year_o["name"] = name + " Infiltration" + sch_infil_year_o["schedule type limits name"] = fraction + sch_infil_year_o["Schedule:Week Name 1"] = sch_infil_week_o + + return sch_infil_year_o + + def sch_occ_add(self, name): + """ + Add IDF schedule objects for occupancy assuming MidRise Apartment building type + Note that a schedule object will be created for each: + day, summer design day, winter design day, week and year + Only schedule for year is returned + + Parameters + ---------- + idf: Oplus IDF object + name: str + Name assigned to occupancy schedule + + Returns + ------- + sch_occ_year_o: Oplus IDFObject + Schedule:Year for occupancy + """ + fraction = self.idf("ScheduleTypeLimits").filter("name", "Fraction").one + + sch_occ_d_o = self.idf.add_object(sch_occ_d_new) + sch_occ_d_o["name"] = name + " Occ Default Schedule" + sch_occ_d_o["schedule type limits name"] = fraction + + sch_occ_sumdes_o = self.idf.add_object(sch_occ_d_new) + sch_occ_sumdes_o["name"] = name + " Occ Summer Design Day" + sch_occ_sumdes_o["schedule type limits name"] = fraction + + sch_occ_windes_o = self.idf.add_object(sch_occ_d_new) + sch_occ_windes_o["name"] = name + " Occ Winter Design Day" + sch_occ_windes_o["schedule type limits name"] = fraction + + sch_occ_week_o = self.idf.add_object(sch_week_new) + sch_occ_week_o["name"] = name + " Occ Schedule:Week:Daily" + sch_occ_week_o["Sunday Schedule:Day Name"] = sch_occ_d_o + sch_occ_week_o["Monday Schedule:Day Name"] = sch_occ_d_o + sch_occ_week_o["Tuesday Schedule:Day Name"] = sch_occ_d_o + sch_occ_week_o["Wednesday Schedule:Day Name"] = sch_occ_d_o + sch_occ_week_o["Thursday Schedule:Day Name"] = sch_occ_d_o + sch_occ_week_o["Friday Schedule:Day Name"] = sch_occ_d_o + sch_occ_week_o["Saturday Schedule:Day Name"] = sch_occ_d_o + sch_occ_week_o["Holiday Schedule:Day Name"] = sch_occ_d_o + sch_occ_week_o["SummerDesignDay Schedule:Day Name"] = sch_occ_sumdes_o + sch_occ_week_o["WinterDesignDay Schedule:Day Name"] = sch_occ_windes_o + sch_occ_week_o["CustomDay1 Schedule:Day Name"] = sch_occ_d_o + sch_occ_week_o["CustomDay2 Schedule:Day Name"] = sch_occ_d_o + + sch_occ_year_o = self.idf.add_object(sch_year_new) + sch_occ_year_o["name"] = name + " Occupancy" + sch_occ_year_o["schedule type limits name"] = fraction + sch_occ_year_o["Schedule:Week Name 1"] = sch_occ_week_o + + return sch_occ_year_o + + def sch_act_add(self, name): + """ + Add IDF schedule objects for activity assuming MidRise Apartment building type + Note that a schedule object will be created for each: + day, summer design day, winter design day, week and year + Only schedule for year is returned + + Parameters + ---------- + idf: Oplus IDF object + name: str + name of year activity schedule + + Returns + ------- + sch_act_year_o: Oplus IDFObject + Schedule:Year for activity + """ + activitylevel1 = self.idf("ScheduleTypeLimits").filter("name", "ActivityLevel").one + + sch_act_d_o = self.idf.add_object(sch_act_d_new) + sch_act_d_o["name"] = name + " Act Default Schedule" + sch_act_d_o["schedule type limits name"] = activitylevel1 + + sch_act_summer_o = self.idf.add_object(sch_act_d_new) + sch_act_summer_o["name"] = name + " Act Summer Design Day" + sch_act_summer_o["schedule type limits name"] = activitylevel1 + + sch_act_winter_o = self.idf.add_object(sch_act_d_new) + sch_act_winter_o["name"] = name + " Act Winter Design Day" + sch_act_winter_o["schedule type limits name"] = activitylevel1 + + sch_act_week_o = self.idf.add_object(sch_week_new) + sch_act_week_o["name"] = name + " Act Schedule:Week:Daily" + sch_act_week_o["Sunday Schedule:Day Name"] = sch_act_d_o + sch_act_week_o["Monday Schedule:Day Name"] = sch_act_d_o + sch_act_week_o["Tuesday Schedule:Day Name"] = sch_act_d_o + sch_act_week_o["Wednesday Schedule:Day Name"] = sch_act_d_o + sch_act_week_o["Thursday Schedule:Day Name"] = sch_act_d_o + sch_act_week_o["Friday Schedule:Day Name"] = sch_act_d_o + sch_act_week_o["Saturday Schedule:Day Name"] = sch_act_d_o + sch_act_week_o["Holiday Schedule:Day Name"] = sch_act_d_o + sch_act_week_o["SummerDesignDay Schedule:Day Name"] = sch_act_summer_o + sch_act_week_o["WinterDesignDay Schedule:Day Name"] = sch_act_winter_o + sch_act_week_o["CustomDay1 Schedule:Day Name"] = sch_act_d_o + sch_act_week_o["CustomDay2 Schedule:Day Name"] = sch_act_d_o + + sch_act_year_o = self.idf.add_object(sch_year_new) + sch_act_year_o["name"] = name + " Activity" + sch_act_year_o["schedule type limits name"] = activitylevel1 + sch_act_year_o["Schedule:Week Name 1"] = sch_act_week_o + + return sch_act_year_o + + def sch_equip_add(self, name): + """ + Add IDF schedule objects for equipment assuming MidRise Apartment building type + Note that a schedule object will be created for each: + day, summer design day, winter design day, week and year + Only schedule for year is returned + + Parameters + ---------- + idf: Oplus IDF object + name: str + Name assigned to equipment schedule + + Returns + ------- + sch_equip_year_o: Oplus IDFObject + Schedule:Year for equipment + """ + fraction = self.idf("ScheduleTypeLimits").filter("name", "Fraction").one + + sch_equip_d_o = self.idf.add_object(sch_equip_d_new) + sch_equip_d_o["name"] = name + " Equip Default Schedule" + sch_equip_d_o["schedule type limits name"] = fraction + + sch_equip_summer_o = self.idf.add_object(sch_equip_d_new) + sch_equip_summer_o["name"] = name + " Equip Summer Design Day" + sch_equip_summer_o["schedule type limits name"] = fraction + + sch_equip_winter_o = self.idf.add_object(sch_equip_d_new) + sch_equip_winter_o["name"] = name + " Equip Winter Design Day" + sch_equip_winter_o["schedule type limits name"] = fraction + + sch_equip_week_o = self.idf.add_object(sch_week_new) + sch_equip_week_o["name"] = name + " Equip Schedule:Week:Daily" + sch_equip_week_o["Sunday Schedule:Day Name"] = sch_equip_d_o + sch_equip_week_o["Monday Schedule:Day Name"] = sch_equip_d_o + sch_equip_week_o["Tuesday Schedule:Day Name"] = sch_equip_d_o + sch_equip_week_o["Wednesday Schedule:Day Name"] = sch_equip_d_o + sch_equip_week_o["Thursday Schedule:Day Name"] = sch_equip_d_o + sch_equip_week_o["Friday Schedule:Day Name"] = sch_equip_d_o + sch_equip_week_o["Saturday Schedule:Day Name"] = sch_equip_d_o + sch_equip_week_o["Holiday Schedule:Day Name"] = sch_equip_d_o + sch_equip_week_o["SummerDesignDay Schedule:Day Name"] = sch_equip_summer_o + sch_equip_week_o["WinterDesignDay Schedule:Day Name"] = sch_equip_winter_o + sch_equip_week_o["CustomDay1 Schedule:Day Name"] = sch_equip_d_o + sch_equip_week_o["CustomDay2 Schedule:Day Name"] = sch_equip_d_o + + sch_equip_year_o = self.idf.add_object(sch_year_new) + sch_equip_year_o["name"] = name + " Equipment" + sch_equip_year_o["schedule type limits name"] = fraction + sch_equip_year_o["Schedule:Week Name 1"] = sch_equip_week_o + + return sch_equip_year_o + + def sch_light_add(self, name): + """ + Add IDF schedule objects for lighting assuming MidRise Apartment building type + Note that a schedule object will be created for each: + day, summer design day, winter design day, week and year + Only schedule for year is returned + + Parameters + ---------- + idf: Oplus IDF object + name: str + Name assigned to lighting schedule + + Returns + ------- + sch_light_year_o: Oplus IDFObject + Schedule:Year for lighting + """ + fraction = self.idf("ScheduleTypeLimits").filter("name", "Fraction").one + + sch_light_d_o = self.idf.add_object(sch_light_d_new) + sch_light_d_o["name"] = name + " Light Default Schedule" + sch_light_d_o["schedule type limits name"] = fraction + + sch_light_summer_o = self.idf.add_object(sch_light_d_new) + sch_light_summer_o["name"] = name + " Light Summer Design Day" + sch_light_summer_o["schedule type limits name"] = fraction + + sch_light_winter_o = self.idf.add_object(sch_light_d_new) + sch_light_winter_o["name"] = "MidriseApartment Light Winter Design Day" + sch_light_winter_o["schedule type limits name"] = fraction + + sch_light_week_o = self.idf.add_object(sch_week_new) + sch_light_week_o["name"] = name + " Light Schedule:Week:Daily" + sch_light_week_o["Sunday Schedule:Day Name"] = sch_light_d_o + sch_light_week_o["Monday Schedule:Day Name"] = sch_light_d_o + sch_light_week_o["Tuesday Schedule:Day Name"] = sch_light_d_o + sch_light_week_o["Wednesday Schedule:Day Name"] = sch_light_d_o + sch_light_week_o["Thursday Schedule:Day Name"] = sch_light_d_o + sch_light_week_o["Friday Schedule:Day Name"] = sch_light_d_o + sch_light_week_o["Saturday Schedule:Day Name"] = sch_light_d_o + sch_light_week_o["Holiday Schedule:Day Name"] = sch_light_d_o + sch_light_week_o["SummerDesignDay Schedule:Day Name"] = sch_light_summer_o + sch_light_week_o["WinterDesignDay Schedule:Day Name"] = sch_light_winter_o + sch_light_week_o["CustomDay1 Schedule:Day Name"] = sch_light_d_o + sch_light_week_o["CustomDay2 Schedule:Day Name"] = sch_light_d_o + + sch_light_year_o = self.idf.add_object(sch_year_new) + sch_light_year_o["name"] = name + " Light" + sch_light_year_o["schedule type limits name"] = fraction + sch_light_year_o["Schedule:Week Name 1"] = sch_light_week_o + + return sch_light_year_o + + def zinf_year_add(self, name, zone_name, schedule_name, cons_year): + """ + Add zone infiltration IDF object based on construction year assuming MidRise Apartment building type + + Parameters + ---------- + idf: Oplus IDF object + name: str + Name assigned to this zone infiltration object + zone_name: Oplus IDFObject + IDF object referring to the zone or zonelist which the zone infiltration object will affect + schedule_name: Oplus IDFObject + IDF object referring to the schedule which the zone infiltration object will refer to + const_year: int or float + Construction year of the building, which will define the infiltration value for the zone + + Returns + ------- + zoneinfil_o: Oplus IDFObject + ZoneInfiltration:DesignFlowRate + """ + if type(cons_year) == int or float: + if cons_year < 2004: + zinf_new = zoneinfil_pre2004_new + zi_cat = "pre2004 " + elif 2004 <= cons_year < 2009: + zinf_new = zoneinfil_post2004_new + zi_cat = "post2004 " + elif 2009 <= cons_year: + zinf_new = zoneinfil_post2009_new + zi_cat = "post2009 " + + zoneinfil_o = self.idf.add_object(zinf_new) + zoneinfil_o["name"] = "Zoneinfil " + zi_cat + name + zoneinfil_o["zone or zonelist name"] = zone_name + zoneinfil_o["schedule name"] = schedule_name + + return zoneinfil_o + + def people_add(self, name, zone_name, sch_occ_name, sch_act_name): + """ + Add people IDF object assuming MidRise Apartment building type + + Parameters + ---------- + idf: Oplus IDF object + name: str + Name assigned to this people object + zone_name: Oplus IDFObject + IDF object referring to the zone or zonelist which the lighting object will affect + sch_occ_name: Oplus IDFObject + IDF object referring to the occupancy schedule which the people object will refer to + sch_act_name: Oplus IDFObject + IDF object referring to the activity schedule which the people object will refer to + + Returns + ------- + people_o: Oplus IDFObject + People + """ + people_o = self.idf.add_object(people_apartment_new) + people_o["name"] = "People " + name + people_o["zone or zonelist name"] = zone_name + people_o["number of people schedule name"] = sch_occ_name + people_o["Activity Level Schedule Name"] = sch_act_name + + return people_o + + def lights_add(self, name, zone_name, sch_light_name): + """ + Add lighting IDF object assuming MidRise Apartment building type + + Parameters + ---------- + idf: Oplus IDF object + name: str + Name assigned to this lighting object + zone_name: Oplus IDFObject + IDF object referring to the zone or zonelist which the lighting object will affect + sch_light_name: Oplus IDFObject + IDF object referring to the lighting schedule which the lighting object will refer to + + Returns + ------- + lights_o: Oplus IDFObject + Lights + """ + lights_o = self.idf.add_object(lights_apartment_new) + lights_o["name"] = "Lighting " + name + lights_o["zone or zonelist name"] = zone_name + lights_o["schedule name"] = sch_light_name + + return lights_o + + def equip_add(self, name, zone_name, sch_equip_name): + """ + Add electric equipment IDF object assuming MidRise Apartment building type + + Parameters + ---------- + idf: Oplus IDF object + name: str + Name assigned to this equipment object + zone_name: Oplus IDFObject + IDF object referring to the zone or zonelist which the equipment object will affect + sch_equip_name: Oplus IDFObject + IDF object referring to the equipment schedule which the equipment object will refer to + + Returns + ------- + elecequip_o: Oplus IDFObject + ElectricEquipment + """ + elecequip_o = self.idf.add_object(elecequip_apartment_new) + elecequip_o["name"] = "Electric Equipment " + name + elecequip_o["zone or zonelist name"] = zone_name + elecequip_o["schedule name"] = sch_equip_name + + return elecequip_o + + diff --git a/requirements.txt b/requirements.txt index 58a270c..5262d69 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,3 @@ +geopy==1.11.0 +oplus==4.6.0 xlrd==1.0.0 diff --git a/tests/simulation/__init__.py b/tests/simulation/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/simulation/test_midrise_idf.py b/tests/simulation/test_midrise_idf.py new file mode 100644 index 0000000..408de98 --- /dev/null +++ b/tests/simulation/test_midrise_idf.py @@ -0,0 +1,9 @@ +from bpeng.simulation import MidRiseApart + + +def test_sch_year_new(): + assert MidRiseApart.sch_year_new == '4' + + +# idf = MidRiseApart() +# print(idf) -- GitLab From fa3729a10de31092e0332802a4eb3c29fa9a3578 Mon Sep 17 00:00:00 2001 From: Michel Date: Tue, 18 Apr 2017 19:36:05 -0400 Subject: [PATCH 02/20] Add test of __init__ function and fix pyLint and pep8 issues of base class --- bpeng/simulation/base.py | 255 ++++++++++++------------ bpeng/simulation/building_hvac_oplus.py | 2 + bpeng/simulation/geometry.py | 4 +- bpeng/simulation/midrise.py | 64 +++--- tests/simulation/test_midrise_idf.py | 5 +- 5 files changed, 168 insertions(+), 162 deletions(-) diff --git a/bpeng/simulation/base.py b/bpeng/simulation/base.py index 0530631..dd44eed 100644 --- a/bpeng/simulation/base.py +++ b/bpeng/simulation/base.py @@ -1,6 +1,11 @@ import abc import math import datetime +import time +import numpy as np +import os +import pandas as pd + from .geometry import (coord_to_meters, tuple_convert_float, fix_degenerate_surface, walls_vertex, floor_vertex, ceiling_vertex, offset_center_ratio) from oplus import IDF @@ -65,12 +70,14 @@ class BaseSim: # file, given the coordinates, construction, zone, and boundary conditions of a surface. def __init__(self, idf_start_file=None): + dir_path = os.path.dirname(os.path.abspath(__file__)) if idf_start_file is None: - idf_source = IDF('initial_idf/empty_start.idf') + idf_source = IDF(os.path.join(dir_path, "initial_idf", "empty_start.idf")) else: idf_source = IDF(idf_start_file) self.idf = idf_source.copy() + self.build_type = self.__class__.__name__ def bsd_add(self, name, cons_name, zone_name, obc, sun_exp, w_exp, nb_v, coords, surface_type=None, obc_obj=None): """ @@ -116,7 +123,7 @@ class BaseSim: raise ValueError("""Length mismatch: Expected axis has {nb_v} elements, new values have {nb_xyz} elements""".format(nb_v=nb_v, nb_xyz=nb_xyz)) - s1 = self.idf.add_object(bsd_new) + s1 = self.idf.add_object(self.bsd_new) s1["name"] = name s1["surface type"] = surface_type s1["construction name"] = cons_name @@ -147,7 +154,7 @@ class BaseSim: ------- z: Zone Oplus IDFObject """ - z = self.idf.add_object(zone_new) + z = self.idf.add_object(self.zone_new) z["name"] = zone_name return z @@ -189,7 +196,7 @@ class BaseSim: for bsd in list_bsd: # Property assignment - s = self.idf.add_object(fsd_new) + s = self.idf.add_object(self.fsd_new) s["name"] = "Sub Surface " + bsd["name"] s["surface type"] = surface_type s["construction name"] = cons_obj @@ -241,7 +248,7 @@ class BaseSim: s1: Oplus IDFObject Shading:Building:Detailed """ - s1 = self.idf.add_object(shading_new) + s1 = self.idf.add_object(self.shading_new) s1["name"] = name s1["transmittance schedule name"] = transmittance_schedule_name s1["number of vertices"] = nb_v @@ -254,7 +261,7 @@ class BaseSim: return s1 def zinf_ach_add(self, name, zone_name, schedule_name, ACH, const_term_coef=None, - temp_term_coef=None, vel_term_coef=None, vel_sq_term_coef=None): + temp_term_coef=None, vel_term_coef=None, vel_sq_term_coef=None): """ Add a ZoneInfiltration:DesignFlowRate IDF object based on ACH value (Air Change per Hour) to a given IDF file and arguments. For more detailed information about ZoneInfiltration:DesignFlowRate object, @@ -288,7 +295,7 @@ class BaseSim: zf1: Oplus IDFObject ZoneInfiltration:DesignFlowRate """ - zf1 = self.idf.add_object(zoneinfil_ACH_new) + zf1 = self.idf.add_object(self.zoneinfil_ACH_new) zf1["name"] = name zf1["zone or zonelist name"] = zone_name zf1["schedule name"] = schedule_name @@ -315,15 +322,15 @@ class BaseSim: zonelist_list: list List of zonelist Oplus IDFObjects """ - zones = idf("zone") + zones = self.idf("zone") zonelist_number = 0 for d in zones: - zonelist_number+=1 + zonelist_number += 1 zonelist_number /= 100 - zonelist_number = math.ceil(zonelist_number) # number of zonelists + zonelist_number = math.ceil(zonelist_number) # number of zonelists zonelist_list = [] for z in list(range(1, zonelist_number+1)): - zl = self.idf.add_object(zonelist_new) + zl = self.idf.add_object(self.zonelist_new) zl["name"] = name + str(z) i = 1 for d in zones: @@ -336,17 +343,16 @@ class BaseSim: return zonelist_list - def idf_creation(self, building_name, building_shapefile, add_shading_analysis=False, building_shading_shapefile=None, - window_to_wall_ratio=0.16, infiltration_value='Automatic', add_people=False, people_value='Automatic', add_equipment=False, - equipment_value='Automatic', add_light=False, light_value='Automatic'): + def idf_creation(self, building_shapefile, add_shading_analysis=False, building_shading_shapefile=None, + window_to_wall_ratio=0.16, infiltration_value='Automatic', add_people=False, people_value='Automatic', + add_equipment=False, equipment_value='Automatic', add_light=False, light_value='Automatic', + build_height_colname='heightroof', geometry_colname='geometry', buildingid_colname='bin', + num_floors_colname='num_floors', cnstrct_yr_colname='cnstrct_yr'): """ - Create EnergyPlus input IDF file from building shapefile + Create EnergyPlus input IDF file from building shapefile. + Parameters ---------- - building_name: str - building name or address - idf_start_file: str or os.path - path to idf emty starting file + file name building_shapefile: pandas.DataFrame building shapefile pandas DataFrame, Building Identification Number (BIN) in DataFrame index add_shading_analysis: boolean @@ -356,7 +362,7 @@ class BaseSim: default is None, must add shading building shapefile if add_shading_analysis is True Building Identification Number (BIN) in DataFrame index window_to_wall_ratio: float - default value for multi-family buildings 16% + default value for multi-family buildings 16%, input must be <1 infiltration_value: float default is 'Automatic' based on building construction year, see function zinf_year_add() in inherited class if a float is inputted, it must be an Air Change per Hour value [1/hour], see function zinf_ach_add() in base class @@ -378,23 +384,33 @@ class BaseSim: Watts per Zone Floor Area [W/m2] default is 'Automatic' based on Residential building see object_input_database.py, variable name: 'lights_apartment_new' + build_height_colname: str + Column name in building_shapefile DataFrame corresponding to building height in feet + geometry_colname: str + Column name in building_shapefile DataFrame corresponding to buidling geometry Polygon + buildingid_colname: str + Column name in building_shapefile DataFrame corresponding to building identification number + num_floors_colname: str + Column name in building_shapefile DataFrame corresponding to number of floors in building + cnstrct_yr_colname: str + Column name in building_shapefile DataFrame corresponding to building construction year + Returns ------- - idf: Oplus idf object + self.idf: Oplus idf object """ - bldg_name = building_name - # idf_save_name = idf_save_name + build_cat = self.build_type # IDF creation start1 = time.clock() - print("Starting {} IDF creation.".format(bldg_name)) + print("Starting IDF creation.") # Load shapefile data build_shp = building_shapefile # Extract geometry Points - geom_div_col = build_shp['geometry'].apply(lambda st: st[st.find("(")+2:st.find(")")]).str.split(', ', expand=True) - geom_div_col.index = list(build_shp['bin']) + geom_div_col = build_shp[geometry_colname].apply(lambda st: st[st.find("(")+3:st.find(")")]).str.split(', ', expand=True) + geom_div_col.index = list(build_shp[buildingid_colname]) # Meter Conversion long_m, lat_m = coord_to_meters() @@ -405,14 +421,14 @@ class BaseSim: geom_div_col = fix_degenerate_surface(geom_div_col) # Convert heighroof to meters - build_shp["heightroof"] *= 0.3048 + build_shp[build_height_colname] *= 0.3048 # Convert number of stories to height in meters* (1 floor = 10ft) # *for shapefiles without "heightroof" column # build_shp["heightroof"] = build_shp["stories"]*10*0.3048 # Database for walls, roof and ceilings # Set origin to 0 - x0, y0 = geom_div_col.iloc[0,0] + x0, y0 = geom_div_col.iloc[0, 0] geom_origin = geom_div_col.copy() for i in range(len(geom_origin.index)): @@ -423,8 +439,8 @@ class BaseSim: lst[1] -= y0 geom_origin.iloc[i, j] = tuple(lst) - build_shp_ep = build_shp.merge(geom_origin, left_on='bin', right_index=True) - build_shp_ep.index = list(build_shp_ep["bin"]) + build_shp_ep = build_shp.merge(geom_origin, left_on=buildingid_colname, right_index=True) + build_shp_ep.index = list(build_shp_ep[buildingid_colname]) # Create list of (x,y,z) coordinates for each floor height for floors, roofs, and walls. # These coordinates will be processed when adding the wall floors and roofs to the IDF file. @@ -437,9 +453,9 @@ class BaseSim: year = [] for bin_ in geom_div_col.index: input_ = geom_origin.ix[bin_] - h = build_shp_ep.ix[bin_]["heightroof"] - num_floor_tmp = build_shp_ep.ix[bin_]["num_floors"] - year_tmp = build_shp_ep.ix[bin_]["cnstrct_yr"] + h = build_shp_ep.ix[bin_][build_height_colname] + num_floor_tmp = build_shp_ep.ix[bin_][num_floors_colname] + year_tmp = build_shp_ep.ix[bin_][cnstrct_yr_colname] h_l = list(np.linspace(0, h, num=(num_floor_tmp + 1))) for i in range(len(h_l) - 1): index.append(str(bin_) + " floor" + str(i + 1)) @@ -461,8 +477,8 @@ class BaseSim: ####################################################################### # Adding buildings for shading analysis - if add_shading_analysis == True: - assert building_shading_shapefile == None, 'No shading building shapefile.' + if add_shading_analysis is True: + assert building_shading_shapefile is not None, 'No shading building shapefile.' # Load shading building shapefile shade_shp = building_shading_shapefile @@ -473,15 +489,15 @@ class BaseSim: # shade_shp = shade_shp[shade_shp.bin != b] # Extract geometry Points - shade_geom_div_col = shade_shp['geometry'].apply(lambda st: st[st.find("(")+2:st.find(")")]).str.split(', ', expand=True) - shade_geom_div_col.index = list(shade_shp['bin']) + shade_geom_div_col = shade_shp[geometry_colname].apply(lambda st: st[st.find("(")+3:st.find(")")]).str.split(', ', expand=True) + shade_geom_div_col.index = list(shade_shp[buildingid_colname]) # Meter Conversion for column in shade_geom_div_col.columns: shade_geom_div_col[column] = shade_geom_div_col[column].apply(lambda x: tuple_convert_float(x, long_m, lat_m)) # Convert heightroof to meters - shade_shp["heightroof"] *= 0.3048 + shade_shp[build_height_colname] *= 0.3048 # Convert number of stories in surrounding buildings to height in meters (1 floor = 10ft) # shade_shp["heightroof"] = shade_shp["stories"]*15*0.3048 @@ -498,8 +514,8 @@ class BaseSim: lst[1] -= y0 shade_origin.iloc[i, j] = tuple(lst) - shade_shp_ep = shade_shp.merge(shade_origin, left_on='bin', right_index=True) - shade_shp_ep.index = list(shade_shp_ep["bin"]) + shade_shp_ep = shade_shp.merge(shade_origin, left_on=buildingid_colname, right_index=True) + shade_shp_ep.index = list(shade_shp_ep[buildingid_colname]) # Create list of (x,y,z) coordinates for floors, roofs, and walls of shading buildings. # These coordinates will be processed when adding the Shading:Building:Detailed to the IDF file. @@ -510,7 +526,7 @@ class BaseSim: index = [] for bin_ in shade_geom_div_col.index: input_ = shade_origin.ix[bin_] - h = shade_shp_ep.ix[bin_]["heightroof"] + h = shade_shp_ep.ix[bin_][build_height_colname] h_l = list(np.linspace(0, h, num=2)) index.append(str(bin_)) hl = h_l[0] # lower height, or floor height, for a given floor @@ -527,10 +543,6 @@ class BaseSim: ####################################################################### # Create IDF - # idf_source = IDF(idf_start_file) - - # idf = idf_source.copy() - # self.idf.save_as(os.path.join(idf_save_path, idf_save_name + ".idf")) # Setting the Solar Distribution Field in Building objects. This value determines how EnergyPlus # treats beam solar radiation and reflectances from exterior surfaces that strike the building and, @@ -551,7 +563,7 @@ class BaseSim: year_l = list(input_ep["year"]) for bin_, num_floor, year in zip(input_ep.index, num_floor_l, year_l): - cons = cons_components(idf, year) + cons = self.cons_components(year) cons_wall = cons[0] cons_groundfloor = cons[1] cons_intfloor = cons[2] @@ -582,7 +594,7 @@ class BaseSim: base_wall_name = "Wall " + str(bin_) zone_name = "Zone " + str(bin_) - zone = zone_add(idf, zone_name=zone_name) + zone = self.zone_add(zone_name=zone_name) zone_list.append(zone) w_l = input_ep.ix[bin_]["walls"] f = input_ep.ix[bin_]["floor"] @@ -591,16 +603,16 @@ class BaseSim: # Walls and Window i = 1 for w in w_l: - bsd_add(idf, base_wall_name + " " + str(i), cons_wall, zone, obc="Outdoors", obc_obj=None, - sun_exp="SunExposed", w_exp="WindExposed", nb_v=4, coords=w, surface_type="Wall") - lst_bsd = list(idf("buildingsurface:detailed").filter("name", base_wall_name + " " + str(i))) - extwindow_wall_ratio_add(idf, cons_window, surface_type="Window", window_to_wall_ratio=window_to_wall_ratio, list_bsd=lst_bsd) + self.bsd_add(base_wall_name + " " + str(i), cons_wall, zone, obc="Outdoors", obc_obj=None, + sun_exp="SunExposed", w_exp="WindExposed", nb_v=4, coords=w, surface_type="Wall") + lst_bsd = list(self.idf("buildingsurface:detailed").filter("name", base_wall_name + " " + str(i))) + self.extwindow_wall_ratio_add(cons_window, surface_type="Window", window_to_wall_ratio=window_to_wall_ratio, list_bsd=lst_bsd) i += 1 # Ground Floor and Roof underneath nb_v_f = len(f) - floor_tmp = bsd_add(idf, floor_name, surface_type="Floor", cons_name=cons_floor, zone_name=zone, - obc=obc_floor, obc_obj=obc_obj_floor, sun_exp="NoSun", w_exp="NoWind", nb_v=nb_v_f, coords=f) + floor_tmp = self.bsd_add(floor_name, surface_type="Floor", cons_name=cons_floor, zone_name=zone, + obc=obc_floor, obc_obj=obc_obj_floor, sun_exp="NoSun", w_exp="NoWind", nb_v=nb_v_f, coords=f) if not new_bdg: roof_tmp["outside boundary condition"] = "Surface" roof_tmp["outside boundary condition object"] = floor_tmp @@ -609,8 +621,8 @@ class BaseSim: # Roof of the zone nb_v_r = len(r) - roof_tmp = bsd_add(idf, ceiling_name, surface_type=surface_type_roof, cons_name=cons_ceiling, zone_name=zone, - obc="Outdoors", obc_obj=None, sun_exp="SunExposed", w_exp="WindExposed", nb_v=nb_v_r, coords=r) + roof_tmp = self.bsd_add(ceiling_name, surface_type=surface_type_roof, cons_name=cons_ceiling, zone_name=zone, + obc="Outdoors", obc_obj=None, sun_exp="SunExposed", w_exp="WindExposed", nb_v=nb_v_r, coords=r) # Next floor outside boundary conditions obc_floor = "Surface" @@ -620,14 +632,14 @@ class BaseSim: # input_ep['cons'] = cons_list # Create schedule Oplus IDFObjects - sch_inf_o = sch_infil_add(idf, 'MidriseApartment') - if add_people == True: - sch_occ_o = sch_occ_add(idf, 'MidriseApartment') - sch_act_o = sch_act_add(idf, 'MidriseApartment') - if add_equipment == True: - sch_equip_o = sch_equip_add(idf, 'MidriseApartment') - if add_light == True: - sch_light_o = sch_light_add(idf, 'MidriseApartment') + sch_inf_o = self.sch_infil_add(build_cat) + if add_people is True: + sch_occ_o = self.sch_occ_add(build_cat) + sch_act_o = self.sch_act_add(build_cat) + if add_equipment is True: + sch_equip_o = self.sch_equip_add(build_cat) + if add_light is True: + sch_light_o = self.sch_light_add(build_cat) # Create a zonelist Oplus IFDObject for each multifamily archetype # Create zone infiltration/people/electric equipment/lighting Oplus IDFObjects for each zonelist @@ -643,10 +655,10 @@ class BaseSim: if zonelist_number == 0: continue zonelist_number /= 100 - zonelist_number = math.ceil(zonelist_number) # number of zonelists + zonelist_number = math.ceil(zonelist_number) # number of zonelists zonelist_list = [] for z in list(range(1, zonelist_number+1)): - zl = self.idf.add_object(zonelist_new) + zl = self.idf.add_object(self.zonelist_new) zl["name"] = "Zonelist " + str(count) i = 1 for d in bdg_list["zone"]: @@ -655,16 +667,16 @@ class BaseSim: i += 1 else: i += 1 - zi = zinf_year_add(idf, str(count), zl, sch_inf_o, previous) - people_o = people_add(idf, 'MidriseApartment'+str(count), zl, sch_occ_o, sch_act_o) - equip_o = equip_add(idf, 'MidriseApartment'+str(count), zl, sch_equip_o) - lights_o = lights_add(idf, 'MidriseApartment'+str(count), zl, sch_light_o) + zi = self.zinf_year_add(str(count), zl, sch_inf_o, previous) + people_o = self.people_add(build_cat+str(count), zl, sch_occ_o, sch_act_o) + equip_o = self.equip_add(build_cat+str(count), zl, sch_equip_o) + lights_o = self.lights_add(build_cat+str(count), zl, sch_light_o) count += 1 previous = y # Shading:Building:Detailed - if add_shading_analysis == True: - assert building_shading_shapefile != None, 'No shading building shapefile.' + if add_shading_analysis is True: + assert building_shading_shapefile is not None, 'No shading building shapefile.' input_shade_ep = input_shade_ep_all.copy() for bin_ in input_shade_ep.index: @@ -675,24 +687,21 @@ class BaseSim: # Walls i = 1 for w in w_l: - sbd_add(idf, base_shading_surf_name + " Wall " + str(i), coords=w, nb_v=4, transmittance_schedule_name=None) + self.sbd_add(base_shading_surf_name + " Wall " + str(i), coords=w, nb_v=4, transmittance_schedule_name=None) i += 1 # Roofs nb_v_r = len(r) - roof_tmp = sbd_add(idf, base_shading_surf_name + " Roof", coords=r, nb_v=nb_v_r, transmittance_schedule_name=None) - - # Save completed IDF file - # self.idf.save_as(os.path.join(idf_save_path, idf_save_name + ".idf")) + roof_tmp = self.sbd_add(base_shading_surf_name + " Roof", coords=r, nb_v=nb_v_r, transmittance_schedule_name=None) # Add objects needed for simulation # SimulationControl - sc = idf("SimulationControl").one + sc = self.idf("SimulationControl").one for i in range(5): sc[i] = "Yes" # RunPeriod - rp = idf("RunPeriod").one + rp = self.idf("RunPeriod").one rp["end month"] = 12 rp["end day of month"] = 31 @@ -717,32 +726,31 @@ class BaseSim: print('Creating ZoneHVAC:IdealLoadsAirSystem objects to idf file') zone_eq_name = "ZoneHVAC:IdealLoadsAirSystem" - temperature_sch_type = add_sch_typelimits(idf, "Temperature", None, None, "Continuous", "temperature") - heating_sch = add_sch_compact(idf, "Heating Schedule", 21, sch_type_limit=temperature_sch_type) - cooling_sch = add_sch_compact(idf, "Cooling Schedule", 21, sch_type_limit=temperature_sch_type) - sch_controltype_setpoints = add_sch_typelimits(idf, "Setpoints", 0, 4, numeric_type="DISCRETE") - sch_on = idf("Schedule:Constant").filter("name", "Always On Discrete").one - for zone in idf("zone"): + temperature_sch_type = add_sch_typelimits(self.idf, "Temperature", None, None, "Continuous", "temperature") + heating_sch = add_sch_compact(self.idf, "Heating Schedule", 21, sch_type_limit=temperature_sch_type) + cooling_sch = add_sch_compact(self.idf, "Cooling Schedule", 21, sch_type_limit=temperature_sch_type) + sch_controltype_setpoints = add_sch_typelimits(self.idf, "Setpoints", 0, 4, numeric_type="DISCRETE") + sch_on = self.idf("Schedule:Constant").filter("name", "Always On Discrete").one + for zone in self.idf("zone"): base_name = zone["name"] node_inlet = zone["name"] + " Supply Inlet Node" name_tmp = zone["name"] + " Ideal Loads System" air_dist_name = zone["name"] + "Thermal Zone Design Spec Zone Air Dist" - sz = add_sizing_zone(idf, zone) - ds_airdistrib = add_designspec_airdist(idf, air_dist_name) - zone_ilas_tmp = add_zone_ideal_airloads(idf, name_tmp, sch_on, node_inlet, - designspec_airdist=ds_airdistrib) - th_dual = add_thermostat_dual_setpoints(idf, base_name + " Thermostat Dual Setpoint", - heating_sch, cooling_sch) - sch_setpoints = add_sch_constant(idf, base_name + " Control Type Sch", 4, - sch_type_limit=sch_controltype_setpoints) - zone_control = add_zone_thermostat(idf, base_name + " Zone Thermostat", zone, sch_setpoints, th_dual) - eqlist = add_zone_equipmentlist(idf, base_name + " Thermal Zone Equipment", zone_eq_type=zone_eq_name, - zone_eq=zone_ilas_tmp["name"], cool_seq=1, heat_seq=1) - eqconnect = add_zone_equipmentconnection(idf, zone, base_name + " Zone Air Node Name", - base_name + " Zone Return Outlet", zone_eqlist=eqlist, - zone_inlet_node=node_inlet) - - print("Time to add ZoneHVAC:IdealLoadsAirSystem IDFObject: {} minutes for {} number of zones.".format((time.clock() - start)/60, len(idf("zone")))) + sz = add_sizing_zone(self.idf, zone) + ds_airdistrib = add_designspec_airdist(self.idf, air_dist_name) + zone_ilas_tmp = add_zone_ideal_airloads(self.idf, name_tmp, sch_on, node_inlet, + designspec_airdist=ds_airdistrib) + th_dual = add_thermostat_dual_setpoints(self.idf, base_name + " Thermostat Dual Setpoint", + heating_sch, cooling_sch) + sch_setpoints = add_sch_constant(self.idf, base_name + " Control Type Sch", 4, + sch_type_limit=sch_controltype_setpoints) + zone_control = add_zone_thermostat(self.idf, base_name + " Zone Thermostat", zone, sch_setpoints, th_dual) + eqlist = add_zone_equipmentlist(self.idf, base_name + " Thermal Zone Equipment", zone_eq_type=zone_eq_name, + zone_eq=zone_ilas_tmp["name"], cool_seq=1, heat_seq=1) + eqconnect = add_zone_equipmentconnection(self.idf, zone, base_name+" Zone Air Node Name", base_name + + " Zone Return Outlet", zone_eqlist=eqlist, zone_inlet_node=node_inlet) + + print("Time to add ZoneHVAC:IdealLoadsAirSystem IDFObject: {} minutes for {} number of zones.".format((time.clock() - start)/60, len(self.idf("zone")))) # print(self.idf("ZoneHVAC:IdealLoadsAirSystem")[0].info()) @@ -763,51 +771,46 @@ class BaseSim: # self.idf.add_object("Output:Variable,*,Site Daylighting Model Sky Clearness,hourly; !- Zone Average []") # self.idf.add_object("Output:Variable,*,Surface Outside Face Sunlit Fraction,hourly; !- Zone Average []") - # Save IDf file ready for simulation - # path_save = os.path.join(idf_save_path, idf_save_name + "_readysim.idf") - # self.idf.save_as(path_save) - - print("Time taken to create IDF for {}: {}".format(bldg_name, (time.clock() - start1)/60)) + print("Time taken to create IDF: {}".format((time.clock() - start1)/60)) return self.idf - @abc.abstractmethod - def sch_infil_add(): - """Add infiltration schedule idf object for zone infiltration idf object.""" + def sch_infil_add(self, name): + """Add infiltration schedule idf object for zone infiltration idf object.""" @abc.abstractmethod - def sch_occ_add(): - """Add occupancy schedule idf object for people idf object.""" + def sch_occ_add(self, name): + """Add occupancy schedule idf object for people idf object.""" @abc.abstractmethod - def sch_act_add(): - """Add activity schedule idf object for people idf object.""" + def sch_act_add(self, name): + """Add activity schedule idf object for people idf object.""" @abc.abstractmethod - def sch_equip_add(): - """Add electric equipment schedule idf object for equipment idf object.""" + def sch_equip_add(self, name): + """Add electric equipment schedule idf object for equipment idf object.""" @abc.abstractmethod - def sch_light_add(): - """Add light schedule idf object for lights idf object.""" + def sch_light_add(self, name): + """Add light schedule idf object for lights idf object.""" @abc.abstractmethod - def zinf_year_add(): - """Add zone infiltration idf object.""" + def zinf_year_add(self, name, zone_name, schedule_name, cons_year): + """Add zone infiltration idf object.""" @abc.abstractmethod - def people_add(): - """Add people idf object for internal gains modeling.""" + def people_add(self, name, zone_name, sch_occ_name, sch_act_name): + """Add people idf object for internal gains modeling.""" @abc.abstractmethod - def equip_add(): - """Add electric equipment idf object for internal gains modeling.""" + def equip_add(self, name, zone_name, sch_equip_name): + """Add electric equipment idf object for internal gains modeling.""" @abc.abstractmethod - def lights_add(): - """Add lights idf object for internal gains modeling.""" + def lights_add(self, name, zone_name, sch_light_name): + """Add lights idf object for internal gains modeling.""" @abc.abstractmethod - def cons_components(): - """Returns the construction list.""" + def cons_components(self, cons_year): + """Returns the construction list.""" diff --git a/bpeng/simulation/building_hvac_oplus.py b/bpeng/simulation/building_hvac_oplus.py index 68b45b5..a9b8437 100644 --- a/bpeng/simulation/building_hvac_oplus.py +++ b/bpeng/simulation/building_hvac_oplus.py @@ -115,6 +115,8 @@ def add_designspec_airdist(idf, name, cool_eff=1, heat_eff=1): designspec[1] = cool_eff designspec[2] = heat_eff + return designspec + def add_sizing_zone(idf, zone_zonel, input_cooling_method="SupplyAirTemperature", input_heating_method="SupplyAirTemperature"): diff --git a/bpeng/simulation/geometry.py b/bpeng/simulation/geometry.py index 4903c23..15a5403 100644 --- a/bpeng/simulation/geometry.py +++ b/bpeng/simulation/geometry.py @@ -125,11 +125,11 @@ def fix_degenerate_surface(geom_div_col): for i in range(len(geom_div_col.columns)): if geom_div_col.loc[bin_, i] is not None: # Skip last point - if (i == len(geom_div_col.columns)-1) or (geom_div_col.loc[bin_,i+1] is None): + if (i == len(geom_div_col.columns)-1) or (geom_div_col.loc[bin_, i+1] is None): continue else: # Calculate distance between current point and next point - temp_dist = twodimdistance(geom_div_col.loc[bin_,i], geom_div_col.loc[bin_,i+1]) + temp_dist = twodimdistance(geom_div_col.loc[bin_, i], geom_div_col.loc[bin_, i+1]) # Record column number for distance below threshold if temp_dist < 0.01: deg_vert.append(i+1) diff --git a/bpeng/simulation/midrise.py b/bpeng/simulation/midrise.py index 6d7c2ea..b7c1908 100644 --- a/bpeng/simulation/midrise.py +++ b/bpeng/simulation/midrise.py @@ -390,19 +390,19 @@ class MidRiseApart(BaseSim): """ fraction = self.idf("ScheduleTypeLimits").filter("name", "Fraction").one - sch_infil_d_o = self.idf.add_object(sch_infil_d_new) + sch_infil_d_o = self.idf.add_object(self.sch_infil_d_new) sch_infil_d_o["name"] = name + " Inf Default Schedule" sch_infil_d_o["schedule type limits name"] = fraction - sch_infil_summer_o = self.idf.add_object(sch_infil_d_new) + sch_infil_summer_o = self.idf.add_object(self.sch_infil_d_new) sch_infil_summer_o["name"] = name + " Inf Summer Design Day" sch_infil_summer_o["schedule type limits name"] = fraction - sch_infil_winter_o = self.idf.add_object(sch_infil_d_new) + sch_infil_winter_o = self.idf.add_object(self.sch_infil_d_new) sch_infil_winter_o["name"] = name + " Inf Winter Design Day" sch_infil_winter_o["schedule type limits name"] = fraction - sch_infil_week_o = self.idf.add_object(sch_week_new) + sch_infil_week_o = self.idf.add_object(self.sch_week_new) sch_infil_week_o["name"] = name + " Inf Schedule:Week:Daily" sch_infil_week_o["Sunday Schedule:Day Name"] = sch_infil_d_o sch_infil_week_o["Monday Schedule:Day Name"] = sch_infil_d_o @@ -417,7 +417,7 @@ class MidRiseApart(BaseSim): sch_infil_week_o["CustomDay1 Schedule:Day Name"] = sch_infil_d_o sch_infil_week_o["CustomDay2 Schedule:Day Name"] = sch_infil_d_o - sch_infil_year_o = self.idf.add_object(sch_year_new) + sch_infil_year_o = self.idf.add_object(self.sch_year_new) sch_infil_year_o["name"] = name + " Infiltration" sch_infil_year_o["schedule type limits name"] = fraction sch_infil_year_o["Schedule:Week Name 1"] = sch_infil_week_o @@ -444,19 +444,19 @@ class MidRiseApart(BaseSim): """ fraction = self.idf("ScheduleTypeLimits").filter("name", "Fraction").one - sch_occ_d_o = self.idf.add_object(sch_occ_d_new) + sch_occ_d_o = self.idf.add_object(self.sch_occ_d_new) sch_occ_d_o["name"] = name + " Occ Default Schedule" sch_occ_d_o["schedule type limits name"] = fraction - sch_occ_sumdes_o = self.idf.add_object(sch_occ_d_new) + sch_occ_sumdes_o = self.idf.add_object(self.sch_occ_d_new) sch_occ_sumdes_o["name"] = name + " Occ Summer Design Day" sch_occ_sumdes_o["schedule type limits name"] = fraction - sch_occ_windes_o = self.idf.add_object(sch_occ_d_new) + sch_occ_windes_o = self.idf.add_object(self.sch_occ_d_new) sch_occ_windes_o["name"] = name + " Occ Winter Design Day" sch_occ_windes_o["schedule type limits name"] = fraction - sch_occ_week_o = self.idf.add_object(sch_week_new) + sch_occ_week_o = self.idf.add_object(self.sch_week_new) sch_occ_week_o["name"] = name + " Occ Schedule:Week:Daily" sch_occ_week_o["Sunday Schedule:Day Name"] = sch_occ_d_o sch_occ_week_o["Monday Schedule:Day Name"] = sch_occ_d_o @@ -471,7 +471,7 @@ class MidRiseApart(BaseSim): sch_occ_week_o["CustomDay1 Schedule:Day Name"] = sch_occ_d_o sch_occ_week_o["CustomDay2 Schedule:Day Name"] = sch_occ_d_o - sch_occ_year_o = self.idf.add_object(sch_year_new) + sch_occ_year_o = self.idf.add_object(self.sch_year_new) sch_occ_year_o["name"] = name + " Occupancy" sch_occ_year_o["schedule type limits name"] = fraction sch_occ_year_o["Schedule:Week Name 1"] = sch_occ_week_o @@ -498,19 +498,19 @@ class MidRiseApart(BaseSim): """ activitylevel1 = self.idf("ScheduleTypeLimits").filter("name", "ActivityLevel").one - sch_act_d_o = self.idf.add_object(sch_act_d_new) + sch_act_d_o = self.idf.add_object(self.sch_act_d_new) sch_act_d_o["name"] = name + " Act Default Schedule" sch_act_d_o["schedule type limits name"] = activitylevel1 - sch_act_summer_o = self.idf.add_object(sch_act_d_new) + sch_act_summer_o = self.idf.add_object(self.sch_act_d_new) sch_act_summer_o["name"] = name + " Act Summer Design Day" sch_act_summer_o["schedule type limits name"] = activitylevel1 - sch_act_winter_o = self.idf.add_object(sch_act_d_new) + sch_act_winter_o = self.idf.add_object(self.sch_act_d_new) sch_act_winter_o["name"] = name + " Act Winter Design Day" sch_act_winter_o["schedule type limits name"] = activitylevel1 - sch_act_week_o = self.idf.add_object(sch_week_new) + sch_act_week_o = self.idf.add_object(self.sch_week_new) sch_act_week_o["name"] = name + " Act Schedule:Week:Daily" sch_act_week_o["Sunday Schedule:Day Name"] = sch_act_d_o sch_act_week_o["Monday Schedule:Day Name"] = sch_act_d_o @@ -525,7 +525,7 @@ class MidRiseApart(BaseSim): sch_act_week_o["CustomDay1 Schedule:Day Name"] = sch_act_d_o sch_act_week_o["CustomDay2 Schedule:Day Name"] = sch_act_d_o - sch_act_year_o = self.idf.add_object(sch_year_new) + sch_act_year_o = self.idf.add_object(self.sch_year_new) sch_act_year_o["name"] = name + " Activity" sch_act_year_o["schedule type limits name"] = activitylevel1 sch_act_year_o["Schedule:Week Name 1"] = sch_act_week_o @@ -552,19 +552,19 @@ class MidRiseApart(BaseSim): """ fraction = self.idf("ScheduleTypeLimits").filter("name", "Fraction").one - sch_equip_d_o = self.idf.add_object(sch_equip_d_new) + sch_equip_d_o = self.idf.add_object(self.sch_equip_d_new) sch_equip_d_o["name"] = name + " Equip Default Schedule" sch_equip_d_o["schedule type limits name"] = fraction - sch_equip_summer_o = self.idf.add_object(sch_equip_d_new) + sch_equip_summer_o = self.idf.add_object(self.sch_equip_d_new) sch_equip_summer_o["name"] = name + " Equip Summer Design Day" sch_equip_summer_o["schedule type limits name"] = fraction - sch_equip_winter_o = self.idf.add_object(sch_equip_d_new) + sch_equip_winter_o = self.idf.add_object(self.sch_equip_d_new) sch_equip_winter_o["name"] = name + " Equip Winter Design Day" sch_equip_winter_o["schedule type limits name"] = fraction - sch_equip_week_o = self.idf.add_object(sch_week_new) + sch_equip_week_o = self.idf.add_object(self.sch_week_new) sch_equip_week_o["name"] = name + " Equip Schedule:Week:Daily" sch_equip_week_o["Sunday Schedule:Day Name"] = sch_equip_d_o sch_equip_week_o["Monday Schedule:Day Name"] = sch_equip_d_o @@ -579,7 +579,7 @@ class MidRiseApart(BaseSim): sch_equip_week_o["CustomDay1 Schedule:Day Name"] = sch_equip_d_o sch_equip_week_o["CustomDay2 Schedule:Day Name"] = sch_equip_d_o - sch_equip_year_o = self.idf.add_object(sch_year_new) + sch_equip_year_o = self.idf.add_object(self.sch_year_new) sch_equip_year_o["name"] = name + " Equipment" sch_equip_year_o["schedule type limits name"] = fraction sch_equip_year_o["Schedule:Week Name 1"] = sch_equip_week_o @@ -606,19 +606,19 @@ class MidRiseApart(BaseSim): """ fraction = self.idf("ScheduleTypeLimits").filter("name", "Fraction").one - sch_light_d_o = self.idf.add_object(sch_light_d_new) + sch_light_d_o = self.idf.add_object(self.sch_light_d_new) sch_light_d_o["name"] = name + " Light Default Schedule" sch_light_d_o["schedule type limits name"] = fraction - sch_light_summer_o = self.idf.add_object(sch_light_d_new) + sch_light_summer_o = self.idf.add_object(self.sch_light_d_new) sch_light_summer_o["name"] = name + " Light Summer Design Day" sch_light_summer_o["schedule type limits name"] = fraction - sch_light_winter_o = self.idf.add_object(sch_light_d_new) + sch_light_winter_o = self.idf.add_object(self.sch_light_d_new) sch_light_winter_o["name"] = "MidriseApartment Light Winter Design Day" sch_light_winter_o["schedule type limits name"] = fraction - sch_light_week_o = self.idf.add_object(sch_week_new) + sch_light_week_o = self.idf.add_object(self.sch_week_new) sch_light_week_o["name"] = name + " Light Schedule:Week:Daily" sch_light_week_o["Sunday Schedule:Day Name"] = sch_light_d_o sch_light_week_o["Monday Schedule:Day Name"] = sch_light_d_o @@ -633,7 +633,7 @@ class MidRiseApart(BaseSim): sch_light_week_o["CustomDay1 Schedule:Day Name"] = sch_light_d_o sch_light_week_o["CustomDay2 Schedule:Day Name"] = sch_light_d_o - sch_light_year_o = self.idf.add_object(sch_year_new) + sch_light_year_o = self.idf.add_object(self.sch_year_new) sch_light_year_o["name"] = name + " Light" sch_light_year_o["schedule type limits name"] = fraction sch_light_year_o["Schedule:Week Name 1"] = sch_light_week_o @@ -663,16 +663,16 @@ class MidRiseApart(BaseSim): """ if type(cons_year) == int or float: if cons_year < 2004: - zinf_new = zoneinfil_pre2004_new + zinf_new = self.zoneinfil_pre2004_new zi_cat = "pre2004 " elif 2004 <= cons_year < 2009: - zinf_new = zoneinfil_post2004_new + zinf_new = self.zoneinfil_post2004_new zi_cat = "post2004 " elif 2009 <= cons_year: - zinf_new = zoneinfil_post2009_new + zinf_new = self.zoneinfil_post2009_new zi_cat = "post2009 " - zoneinfil_o = self.idf.add_object(zinf_new) + zoneinfil_o = self.idf.add_object(self.zinf_new) zoneinfil_o["name"] = "Zoneinfil " + zi_cat + name zoneinfil_o["zone or zonelist name"] = zone_name zoneinfil_o["schedule name"] = schedule_name @@ -700,7 +700,7 @@ class MidRiseApart(BaseSim): people_o: Oplus IDFObject People """ - people_o = self.idf.add_object(people_apartment_new) + people_o = self.idf.add_object(self.people_apartment_new) people_o["name"] = "People " + name people_o["zone or zonelist name"] = zone_name people_o["number of people schedule name"] = sch_occ_name @@ -727,7 +727,7 @@ class MidRiseApart(BaseSim): lights_o: Oplus IDFObject Lights """ - lights_o = self.idf.add_object(lights_apartment_new) + lights_o = self.idf.add_object(self.lights_apartment_new) lights_o["name"] = "Lighting " + name lights_o["zone or zonelist name"] = zone_name lights_o["schedule name"] = sch_light_name @@ -753,7 +753,7 @@ class MidRiseApart(BaseSim): elecequip_o: Oplus IDFObject ElectricEquipment """ - elecequip_o = self.idf.add_object(elecequip_apartment_new) + elecequip_o = self.idf.add_object(self.elecequip_apartment_new) elecequip_o["name"] = "Electric Equipment " + name elecequip_o["zone or zonelist name"] = zone_name elecequip_o["schedule name"] = sch_equip_name diff --git a/tests/simulation/test_midrise_idf.py b/tests/simulation/test_midrise_idf.py index 408de98..13ea5b3 100644 --- a/tests/simulation/test_midrise_idf.py +++ b/tests/simulation/test_midrise_idf.py @@ -5,5 +5,6 @@ def test_sch_year_new(): assert MidRiseApart.sch_year_new == '4' -# idf = MidRiseApart() -# print(idf) +def test_init(): + idf = MidRiseApart() + assert idf.build_type == 'MidRiseApart' -- GitLab From 8f40627acbbb914d806ea8eaea023a0aa1326fc5 Mon Sep 17 00:00:00 2001 From: Michel Date: Wed, 19 Apr 2017 18:31:35 -0400 Subject: [PATCH 03/20] Finalize idf_creation function and create test functions. --- bpeng/simulation/base.py | 158 +++++++++++++++------------ bpeng/simulation/midrise.py | 6 +- tests/simulation/test_midrise_idf.py | 49 ++++++++- 3 files changed, 135 insertions(+), 78 deletions(-) diff --git a/bpeng/simulation/base.py b/bpeng/simulation/base.py index dd44eed..e5ff9e1 100644 --- a/bpeng/simulation/base.py +++ b/bpeng/simulation/base.py @@ -299,7 +299,7 @@ class BaseSim: zf1["name"] = name zf1["zone or zonelist name"] = zone_name zf1["schedule name"] = schedule_name - zf1["Air Changes per Hour {1/hr}"] = ACH + zf1["Air Changes per Hour"] = ACH zf1["Constant Term Coefficient"] = const_term_coef zf1["Constant Term Coefficient"] = temp_term_coef zf1["Constant Term Coefficient"] = vel_term_coef @@ -314,6 +314,7 @@ class BaseSim: Parameters ---------- idf: Oplus IDF object + name: str Name assigned to zonelist @@ -344,60 +345,56 @@ class BaseSim: return zonelist_list def idf_creation(self, building_shapefile, add_shading_analysis=False, building_shading_shapefile=None, - window_to_wall_ratio=0.16, infiltration_value='Automatic', add_people=False, people_value='Automatic', - add_equipment=False, equipment_value='Automatic', add_light=False, light_value='Automatic', - build_height_colname='heightroof', geometry_colname='geometry', buildingid_colname='bin', - num_floors_colname='num_floors', cnstrct_yr_colname='cnstrct_yr'): + window_to_wall_ratio=0.16, infiltration_value='Automatic', add_people=False, + people_value='Automatic', add_equipment=False, equipment_value='Automatic', add_light=False, + light_value='Automatic', solar_dist_method="FullExterior", build_height_colname='heightroof', + geometry_colname='geometry', buildingid_colname='bin', num_floors_colname='num_floors', + cnstrct_yr_colname='cnstrct_yr'): """ Create EnergyPlus input IDF file from building shapefile. Parameters ---------- - building_shapefile: pandas.DataFrame - building shapefile pandas DataFrame, Building Identification Number (BIN) in DataFrame index - add_shading_analysis: boolean - add surrounding building for shading analysis if True, default is False - building_shading_shapefile: pandas.DataFrame - surrounding buildings shapefile in pandas DataFrame - default is None, must add shading building shapefile if add_shading_analysis is True - Building Identification Number (BIN) in DataFrame index - window_to_wall_ratio: float - default value for multi-family buildings 16%, input must be <1 - infiltration_value: float - default is 'Automatic' based on building construction year, see function zinf_year_add() in inherited class - if a float is inputted, it must be an Air Change per Hour value [1/hour], see function zinf_ach_add() in base class - add_people: boolean - add people internal gain components if True, default is False - people_value: float - occupancy value [person/m2] - default is 'Automatic' based on ASHRAE 189.1-2009 - MidriseApartment - Apartment - CZ4-8 from Open Studio - see object_input_database.py, variable name: 'people_apartment_new' - add_equipment: boolean - add equipment internal gain components if True, default is False - equipment_value: float - Watts per Zone Floor Area [W/m2] - default is 'Automatic' based on Residential building - see object_input_database.py, variable name: 'elecequip_apartment_new' - add_light: boolean - add light internal gain components if True, default is False - light_value: float - Watts per Zone Floor Area [W/m2] - default is 'Automatic' based on Residential building - see object_input_database.py, variable name: 'lights_apartment_new' - build_height_colname: str - Column name in building_shapefile DataFrame corresponding to building height in feet - geometry_colname: str - Column name in building_shapefile DataFrame corresponding to buidling geometry Polygon - buildingid_colname: str - Column name in building_shapefile DataFrame corresponding to building identification number - num_floors_colname: str - Column name in building_shapefile DataFrame corresponding to number of floors in building - cnstrct_yr_colname: str - Column name in building_shapefile DataFrame corresponding to building construction year + building_shapefile (pandas.DataFrame): Building shapefile pandas DataFrame, Building Identification + Number (BIN) in DataFrame index + add_shading_analysis (boolean): Add surrounding building for shading analysis if True, default is False + building_shading_shapefile (pandas.DataFrame): Surrounding buildings shapefile in pandas DataFrame + Default is None, must add shading building shapefile if + add_shading_analysis is True + Building Identification Number (BIN) in DataFrame index + window_to_wall_ratio (float): Default value for multi-family buildings 16%, input must be <1 + infiltration_value (float): Default is 'Automatic' based on building construction year, see function + zinf_year_add() in inherited class + If a float is inputted, it must be an Air Change per Hour value [1/hour], + see function zinf_ach_add() in base class + add_people (bool): Add people internal gain components if True, default is False + people_value (float): Occupancy value [person/m2] + Default is 'Automatic' based on 'ASHRAE 189.1-2009 - MidriseApartment - Apartment - + CZ4-8' from Open Studio. See object_input_database.py, variable name: 'people_apartment_new' + add_equipment (bool): Add equipment internal gain components if True, default is False + equipment_value (float): Watts per Zone Floor Area [W/m2] + Default is 'Automatic' based on Residential building + See object_input_database.py, variable name: 'elecequip_apartment_new' + add_light (bool): Add light internal gain components if True, default is False + light_value (float): Watts per Zone Floor Area [W/m2] + Default is 'Automatic' based on Residential building + See object_input_database.py, variable name: 'lights_apartment_new' + solar_dist_method (str): Setting the Solar Distribution Field in Building objects. This value determines how + EnergyPlus treats beam solar radiation and reflectances from exterior surfaces that + strike the building and, ultimately, enter the zone. + There are five choices: MinimalShadowing, FullExterior (default) and + FullInteriorAndExterior, FullExteriorWithReflections, + FullInteriorAndExteriorWithReflections. + See EnergyPlus InputOutputReference documentation for more information + build_height_colname (str): Column name in building_shapefile DataFrame corresponding to building height in feet + geometry_colname (str): Column name in building_shapefile DataFrame corresponding to buidling geometry Polygon + buildingid_colname (str): Column name in building_shapefile DataFrame corresponding to building identification number + num_floors_colname (str): Column name in building_shapefile DataFrame corresponding to number of floors in building + cnstrct_yr_colname (str): Column name in building_shapefile DataFrame corresponding to building construction year Returns ------- - self.idf: Oplus idf object + self.idf (Oplus idf object) """ build_cat = self.build_type @@ -408,6 +405,7 @@ class BaseSim: # Load shapefile data build_shp = building_shapefile + # TODO: Create function for geometry extraction for building shapefile # Extract geometry Points geom_div_col = build_shp[geometry_colname].apply(lambda st: st[st.find("(")+3:st.find(")")]).str.split(', ', expand=True) geom_div_col.index = list(build_shp[buildingid_colname]) @@ -477,8 +475,9 @@ class BaseSim: ####################################################################### # Adding buildings for shading analysis + # TODO: Create function to extract geometry from shading building shapefiles if add_shading_analysis is True: - assert building_shading_shapefile is not None, 'No shading building shapefile.' + assert building_shading_shapefile is not None, "No shading building shapefile input." # Load shading building shapefile shade_shp = building_shading_shapefile @@ -544,23 +543,20 @@ class BaseSim: ####################################################################### # Create IDF - # Setting the Solar Distribution Field in Building objects. This value determines how EnergyPlus - # treats beam solar radiation and reflectances from exterior surfaces that strike the building and, - # ultimately, enter the zone. There are five choices: MinimalShadowing, FullExterior and - # FullInteriorAndExterior, FullExteriorWithReflections, FullInteriorAndExteriorWithReflections. - # See EnergyPlus InputOutputReference documentation for more information for i in self.idf("Building"): - i['Solar Distribution'] = "FullExterior" + i['Solar Distribution'] = solar_dist_method # BuildingSurface:Detailed, FenestrationSurface:Detailed and Zones # One window object is added per wall with outdoor outside boundary condition # One zone is added per floor and per building. + # TODO: Create function to add BuildingSurface:Detailed objects to idf input_ep = input_ep_all.copy() zone_list = [] # cons_list = [] num_floor_l = list(input_ep["num_floor"]) year_l = list(input_ep["year"]) + roof_tmp = pd.DataFrame() for bin_, num_floor, year in zip(input_ep.index, num_floor_l, year_l): cons = self.cons_components(year) @@ -606,13 +602,15 @@ class BaseSim: self.bsd_add(base_wall_name + " " + str(i), cons_wall, zone, obc="Outdoors", obc_obj=None, sun_exp="SunExposed", w_exp="WindExposed", nb_v=4, coords=w, surface_type="Wall") lst_bsd = list(self.idf("buildingsurface:detailed").filter("name", base_wall_name + " " + str(i))) - self.extwindow_wall_ratio_add(cons_window, surface_type="Window", window_to_wall_ratio=window_to_wall_ratio, list_bsd=lst_bsd) + self.extwindow_wall_ratio_add(cons_window, surface_type="Window", + window_to_wall_ratio=window_to_wall_ratio, list_bsd=lst_bsd) i += 1 # Ground Floor and Roof underneath nb_v_f = len(f) floor_tmp = self.bsd_add(floor_name, surface_type="Floor", cons_name=cons_floor, zone_name=zone, - obc=obc_floor, obc_obj=obc_obj_floor, sun_exp="NoSun", w_exp="NoWind", nb_v=nb_v_f, coords=f) + obc=obc_floor, obc_obj=obc_obj_floor, sun_exp="NoSun", w_exp="NoWind", + nb_v=nb_v_f, coords=f) if not new_bdg: roof_tmp["outside boundary condition"] = "Surface" roof_tmp["outside boundary condition object"] = floor_tmp @@ -621,8 +619,9 @@ class BaseSim: # Roof of the zone nb_v_r = len(r) - roof_tmp = self.bsd_add(ceiling_name, surface_type=surface_type_roof, cons_name=cons_ceiling, zone_name=zone, - obc="Outdoors", obc_obj=None, sun_exp="SunExposed", w_exp="WindExposed", nb_v=nb_v_r, coords=r) + roof_tmp = self.bsd_add(ceiling_name, surface_type=surface_type_roof, cons_name=cons_ceiling, + zone_name=zone, obc="Outdoors", obc_obj=None, sun_exp="SunExposed", + w_exp="WindExposed", nb_v=nb_v_r, coords=r) # Next floor outside boundary conditions obc_floor = "Surface" @@ -643,9 +642,8 @@ class BaseSim: # Create a zonelist Oplus IFDObject for each multifamily archetype # Create zone infiltration/people/electric equipment/lighting Oplus IDFObjects for each zonelist + # TODO: Create function to create zonelist, zoneinfiltration, people, equipment and light objects - zoneinf_list = [] - prevyear_list = [] previous = 0 count = 1 thisyear = datetime.datetime.now().year @@ -667,16 +665,33 @@ class BaseSim: i += 1 else: i += 1 - zi = self.zinf_year_add(str(count), zl, sch_inf_o, previous) - people_o = self.people_add(build_cat+str(count), zl, sch_occ_o, sch_act_o) - equip_o = self.equip_add(build_cat+str(count), zl, sch_equip_o) - lights_o = self.lights_add(build_cat+str(count), zl, sch_light_o) + if infiltration_value == 'Automatic': + self.zinf_year_add(str(count), zl, sch_inf_o, previous) + elif isinstance(infiltration_value, float or int): + self.zinf_ach_add(name='Zoneinfil ACH '+build_cat+str(count), zone_name=zl, schedule_name=sch_inf_o, + ACH=infiltration_value, const_term_coef=None, temp_term_coef=None, + vel_term_coef=None, vel_sq_term_coef=None) + else: + raise ValueError("""Missing infiltration value input, put 'Automatic' for + infiltration value based on building construction year.""") + if add_people is True: + people_o = self.people_add(build_cat+str(count), zl, sch_occ_o, sch_act_o) + if isinstance(people_value, float or int): + people_o['People per Zone Floor Area'] = people_value + if add_equipment is True: + equip_o = self.equip_add(build_cat+str(count), zl, sch_equip_o) + if isinstance(equipment_value, float or int): + equip_o['Watts per Zone Floor Area'] = equipment_value + if add_light is True: + lights_o = self.lights_add(build_cat+str(count), zl, sch_light_o) + if isinstance(light_value, float or int): + lights_o['Watts per Zone Floor Area'] = light_value count += 1 previous = y # Shading:Building:Detailed if add_shading_analysis is True: - assert building_shading_shapefile is not None, 'No shading building shapefile.' + assert building_shading_shapefile is not None, "No shading building shapefile input." input_shade_ep = input_shade_ep_all.copy() for bin_ in input_shade_ep.index: @@ -687,11 +702,13 @@ class BaseSim: # Walls i = 1 for w in w_l: - self.sbd_add(base_shading_surf_name + " Wall " + str(i), coords=w, nb_v=4, transmittance_schedule_name=None) + self.sbd_add(base_shading_surf_name + " Wall " + str(i), coords=w, nb_v=4, + transmittance_schedule_name=None) i += 1 # Roofs nb_v_r = len(r) - roof_tmp = self.sbd_add(base_shading_surf_name + " Roof", coords=r, nb_v=nb_v_r, transmittance_schedule_name=None) + roof_tmp = self.sbd_add(base_shading_surf_name + " Roof", coords=r, nb_v=nb_v_r, + transmittance_schedule_name=None) # Add objects needed for simulation # SimulationControl @@ -738,8 +755,7 @@ class BaseSim: air_dist_name = zone["name"] + "Thermal Zone Design Spec Zone Air Dist" sz = add_sizing_zone(self.idf, zone) ds_airdistrib = add_designspec_airdist(self.idf, air_dist_name) - zone_ilas_tmp = add_zone_ideal_airloads(self.idf, name_tmp, sch_on, node_inlet, - designspec_airdist=ds_airdistrib) + zone_ilas_tmp = add_zone_ideal_airloads(self.idf, name_tmp, sch_on, node_inlet) th_dual = add_thermostat_dual_setpoints(self.idf, base_name + " Thermostat Dual Setpoint", heating_sch, cooling_sch) sch_setpoints = add_sch_constant(self.idf, base_name + " Control Type Sch", 4, @@ -750,10 +766,12 @@ class BaseSim: eqconnect = add_zone_equipmentconnection(self.idf, zone, base_name+" Zone Air Node Name", base_name + " Zone Return Outlet", zone_eqlist=eqlist, zone_inlet_node=node_inlet) - print("Time to add ZoneHVAC:IdealLoadsAirSystem IDFObject: {} minutes for {} number of zones.".format((time.clock() - start)/60, len(self.idf("zone")))) + print("Time to add ZoneHVAC:IdealLoadsAirSystem IDFObject: {} minutes for {} zones.".format((time.clock() - start)/60, len(self.idf("zone")))) # print(self.idf("ZoneHVAC:IdealLoadsAirSystem")[0].info()) + # TODO: Add option to choose output variables and tables + self.idf.add_object("Output:VariableDictionary,IDF;") # self.idf.add_object("Output:Variable,, Site Indoor Air Drybulb Temperature,hourly;") # self.idf.add_object("Output:Variable,*,Zone Operative Temperature,hourly; !- Zone Average [C];") diff --git a/bpeng/simulation/midrise.py b/bpeng/simulation/midrise.py index b7c1908..73fecdb 100644 --- a/bpeng/simulation/midrise.py +++ b/bpeng/simulation/midrise.py @@ -155,7 +155,7 @@ class MidRiseApart(BaseSim): 0.16; !- Value Until Time 16""" # Daily Infiltration Schedule ("MidriseApartment Infil Default Schedule" from Open Studio) - sch_infil_d_new = """Schedule:Day:Interval + sch_infil_d_new = """Schedule:Day:Interval, , !- Name , !- Schedule Type Limits Name No, !- Interpolate to Timestep @@ -642,7 +642,7 @@ class MidRiseApart(BaseSim): def zinf_year_add(self, name, zone_name, schedule_name, cons_year): """ - Add zone infiltration IDF object based on construction year assuming MidRise Apartment building type + Add zone infiltration IDF object based on construction year assuming MidRise Apartment building type. Parameters ---------- @@ -672,7 +672,7 @@ class MidRiseApart(BaseSim): zinf_new = self.zoneinfil_post2009_new zi_cat = "post2009 " - zoneinfil_o = self.idf.add_object(self.zinf_new) + zoneinfil_o = self.idf.add_object(zinf_new) zoneinfil_o["name"] = "Zoneinfil " + zi_cat + name zoneinfil_o["zone or zonelist name"] = zone_name zoneinfil_o["schedule name"] = schedule_name diff --git a/tests/simulation/test_midrise_idf.py b/tests/simulation/test_midrise_idf.py index 13ea5b3..28a885c 100644 --- a/tests/simulation/test_midrise_idf.py +++ b/tests/simulation/test_midrise_idf.py @@ -1,10 +1,49 @@ +import pandas as pd + from bpeng.simulation import MidRiseApart -def test_sch_year_new(): - assert MidRiseApart.sch_year_new == '4' +class TestMidRiseApart: + + colnames_list = ['bbl', + 'bin', + 'built_code', + 'cnstrct_yr', + 'date_lstmo', + 'doitt_id', + 'feat_code', + 'geometry', + 'groundelev', + 'heightroof', + 'lststatype', + 'name', + 'num_floors', + 'shape_area', + 'shape_len', + 'sub_code', + 'time_lstmo'] + + geometry_poly = 'MULTIPOLYGON(((-73.94641126946065 40.79089312357564, -73.94652458117535 40.79073642966144, ' \ + '-73.9466023711673 40.79076892427322, -73.94650177155994 40.79090804098926, ' \ + '-73.94647668522865 40.790897561923, -73.94646397442928 40.79091513919471, ' \ + '-73.94641126946065 40.79089312357564))' + + values_list = [[1016320026, 1051959.0, 'E', 1910.0, '2009-02-14', 744227.0, 2100.0, + geometry_poly, + 10.0, 15.0364937268, 'Constructed', "nan", 4.0, 1543.26117443, + 179.44512646599998, 210000.0, '00:00:00.000']] + + test_shp = pd.DataFrame(values_list, columns=colnames_list) + + def setup_class(self): + self.midrise_idf = MidRiseApart() + def test_init(self): + assert self.midrise_idf.build_type == 'MidRiseApart' -def test_init(): - idf = MidRiseApart() - assert idf.build_type == 'MidRiseApart' + def test_idf_creation(self): + self.midrise_idf.idf_creation(building_shapefile=self.test_shp, add_shading_analysis=False, add_people=True, + add_equipment=True, add_light=True, infiltration_value=1.5) + bsd = self.midrise_idf.idf("BuildingSurface:Detailed").filter('name', 'Wall 1051959.0 floor1 1').one + assert bsd['name'] == 'Wall 1051959.0 floor1 1' + assert bsd['Construction Name']['Name'] == 'Steel Frame Res Ext Wall_stucco_pre1980' -- GitLab From 806940655d531232b28b23122f064b853b85974e Mon Sep 17 00:00:00 2001 From: Michel Date: Thu, 20 Apr 2017 19:15:41 -0400 Subject: [PATCH 04/20] Add Polygon points extraction for idf_creation --- bpeng/simulation/base.py | 165 ++++++++++++++++----------- bpeng/simulation/geometry.py | 94 ++++++++++++--- bpeng/simulation/midrise.py | 5 +- tests/simulation/test_midrise_idf.py | 2 +- 4 files changed, 182 insertions(+), 84 deletions(-) diff --git a/bpeng/simulation/base.py b/bpeng/simulation/base.py index e5ff9e1..e26b2c0 100644 --- a/bpeng/simulation/base.py +++ b/bpeng/simulation/base.py @@ -6,7 +6,7 @@ import numpy as np import os import pandas as pd -from .geometry import (coord_to_meters, tuple_convert_float, fix_degenerate_surface, +from .geometry import (coord_to_meters, tuple_convert_float, fix_degenerate_surface, tuplelist_to_df, walls_vertex, floor_vertex, ceiling_vertex, offset_center_ratio) from oplus import IDF from .design_days import add_dday @@ -69,7 +69,20 @@ class BaseSim: # Functions using oplus IDFObjects and IDF classes to add the geometry of the building envelope to and IDF # file, given the coordinates, construction, zone, and boundary conditions of a surface. - def __init__(self, idf_start_file=None): + def __init__(self, building_shapefile, idf_start_file=None, building_shading_shapefile=None): + """ + building_shapefile: pandas.DataFrame + Building shapefile pandas DataFrame, Building Identification Number (BIN) in DataFrame index + + idf_start_file: str + String to idf starting file + Default is None, will fetch 'empty_start.idf' in repo + + building_shading_shapefile: pandas.DataFrame + Surrounding buildings shapefile in pandas DataFrame + Default is None, must add shading building shapefile if add_shading_analysis is True + Building Identification Number (BIN) in DataFrame index + """ dir_path = os.path.dirname(os.path.abspath(__file__)) if idf_start_file is None: idf_source = IDF(os.path.join(dir_path, "initial_idf", "empty_start.idf")) @@ -78,6 +91,8 @@ class BaseSim: self.idf = idf_source.copy() self.build_type = self.__class__.__name__ + self.building_shp = building_shapefile + self.building_shading_shp = building_shading_shapefile def bsd_add(self, name, cons_name, zone_name, obc, sun_exp, w_exp, nb_v, coords, surface_type=None, obc_obj=None): """ @@ -344,57 +359,77 @@ class BaseSim: return zonelist_list - def idf_creation(self, building_shapefile, add_shading_analysis=False, building_shading_shapefile=None, - window_to_wall_ratio=0.16, infiltration_value='Automatic', add_people=False, - people_value='Automatic', add_equipment=False, equipment_value='Automatic', add_light=False, - light_value='Automatic', solar_dist_method="FullExterior", build_height_colname='heightroof', - geometry_colname='geometry', buildingid_colname='bin', num_floors_colname='num_floors', - cnstrct_yr_colname='cnstrct_yr'): + # pytlint: disable=too-many-statements + def idf_creation(self, add_shading_analysis=False, window_to_wall_ratio=0.16, infiltration_value='Automatic', + add_people=False, people_value='Automatic', add_equipment=False, equipment_value='Automatic', + add_light=False, light_value='Automatic', solar_dist_method="FullExterior", + build_height_colname='heightroof', geometry_colname='geometry', buildingid_colname='bin', + num_floors_colname='num_floors', cnstrct_yr_colname='cnstrct_yr'): """ Create EnergyPlus input IDF file from building shapefile. Parameters - ---------- - building_shapefile (pandas.DataFrame): Building shapefile pandas DataFrame, Building Identification - Number (BIN) in DataFrame index - add_shading_analysis (boolean): Add surrounding building for shading analysis if True, default is False - building_shading_shapefile (pandas.DataFrame): Surrounding buildings shapefile in pandas DataFrame - Default is None, must add shading building shapefile if - add_shading_analysis is True - Building Identification Number (BIN) in DataFrame index - window_to_wall_ratio (float): Default value for multi-family buildings 16%, input must be <1 - infiltration_value (float): Default is 'Automatic' based on building construction year, see function - zinf_year_add() in inherited class - If a float is inputted, it must be an Air Change per Hour value [1/hour], - see function zinf_ach_add() in base class - add_people (bool): Add people internal gain components if True, default is False - people_value (float): Occupancy value [person/m2] - Default is 'Automatic' based on 'ASHRAE 189.1-2009 - MidriseApartment - Apartment - - CZ4-8' from Open Studio. See object_input_database.py, variable name: 'people_apartment_new' - add_equipment (bool): Add equipment internal gain components if True, default is False - equipment_value (float): Watts per Zone Floor Area [W/m2] - Default is 'Automatic' based on Residential building - See object_input_database.py, variable name: 'elecequip_apartment_new' - add_light (bool): Add light internal gain components if True, default is False - light_value (float): Watts per Zone Floor Area [W/m2] - Default is 'Automatic' based on Residential building - See object_input_database.py, variable name: 'lights_apartment_new' - solar_dist_method (str): Setting the Solar Distribution Field in Building objects. This value determines how - EnergyPlus treats beam solar radiation and reflectances from exterior surfaces that - strike the building and, ultimately, enter the zone. - There are five choices: MinimalShadowing, FullExterior (default) and - FullInteriorAndExterior, FullExteriorWithReflections, - FullInteriorAndExteriorWithReflections. - See EnergyPlus InputOutputReference documentation for more information - build_height_colname (str): Column name in building_shapefile DataFrame corresponding to building height in feet - geometry_colname (str): Column name in building_shapefile DataFrame corresponding to buidling geometry Polygon - buildingid_colname (str): Column name in building_shapefile DataFrame corresponding to building identification number - num_floors_colname (str): Column name in building_shapefile DataFrame corresponding to number of floors in building - cnstrct_yr_colname (str): Column name in building_shapefile DataFrame corresponding to building construction year + -- + add_shading_analysis: bool + Add surrounding building for shading analysis if True, default is False + + window_to_wall_ratio: float + Default value for multi-family buildings 16%, input must be <1 + + infiltration_value: float + Default is 'Automatic' based on building construction year, see function zinf_year_add() in + inherited class. If a float is inputted, it must be an Air Change per Hour value [1/hour], + see function zinf_ach_add() in base class + + add_people: bool + Add people internal gain components if True, default is False + + people_value: float + Occupancy value [person/m2]. Default is 'Automatic' based on + 'ASHRAE 189.1-2009 - MidriseApartment - Apartment - CZ4-8' from Open Studio. + See object_input_database.py, variable name: 'people_apartment_new' + + add_equipment: bool + Add equipment internal gain components if True, default is False + + equipment_value: float + Watts per Zone Floor Area [W/m2] + Default is 'Automatic' based on Residential building + See object_input_database.py, variable name: 'elecequip_apartment_new' + + add_light: bool + Add light internal gain components if True, default is False + + light_value: float + Watts per Zone Floor Area [W/m2] + Default is 'Automatic' based on Residential building + See object_input_database.py, variable name: 'lights_apartment_new' + + solar_dist_method: str + Setting the Solar Distribution Field in Building objects. This value determines how EnergyPlus treats + beam solar radiation and reflectances from exterior surfaces that strike the building and, ultimately, + enter the zone. There are five choices: MinimalShadowing, FullExterior (default) and + FullInteriorAndExterior, FullExteriorWithReflections, FullInteriorAndExteriorWithReflections. + See EnergyPlus InputOutputReference documentation for more information. + + build_height_colname: str + Column name in building_shapefile DataFrame corresponding to building height in feet + + geometry_colname: str + Column name in building_shapefile DataFrame corresponding to buidling geometry Polygon + + buildingid_colname: str + Column name in building_shapefile DataFrame corresponding to building identification number + + num_floors_colname: str + Column name in building_shapefile DataFrame corresponding to number of floors in building + + cnstrct_yr_colname: str + Column name in building_shapefile DataFrame corresponding to building construction year Returns - ------- - self.idf (Oplus idf object) + -- + oplus.IDF: Oplus idf object """ build_cat = self.build_type @@ -403,17 +438,19 @@ class BaseSim: print("Starting IDF creation.") # Load shapefile data - build_shp = building_shapefile - - # TODO: Create function for geometry extraction for building shapefile - # Extract geometry Points - geom_div_col = build_shp[geometry_colname].apply(lambda st: st[st.find("(")+3:st.find(")")]).str.split(', ', expand=True) - geom_div_col.index = list(build_shp[buildingid_colname]) + build_shp = self.building_shp # Meter Conversion long_m, lat_m = coord_to_meters() - for column in geom_div_col.columns: - geom_div_col[column] = geom_div_col[column].apply(lambda x: tuple_convert_float(x, long_m, lat_m)) + + # TODO: Create function for geometry extraction for building shapefile + # Extract geometry Points + geom_div_col = tuplelist_to_df(df=build_shp, geom_colname='geometry', bin_colname='bin', + conversion_long=long_m, conversion_lat=lat_m) + # geom_div_col = build_shp[geometry_colname].apply(lambda st: st[st.find("(")+2:st.find(")")]).str.split(', ', expand=True) + # geom_div_col.index = list(build_shp[buildingid_colname]) + # for column in geom_div_col.columns: + # geom_div_col[column] = geom_div_col[column].apply(lambda x: tuple_convert_float(x, long_m, lat_m)) # Remove points that will create denegerate surfaces geom_div_col = fix_degenerate_surface(geom_div_col) @@ -477,10 +514,10 @@ class BaseSim: # Adding buildings for shading analysis # TODO: Create function to extract geometry from shading building shapefiles if add_shading_analysis is True: - assert building_shading_shapefile is not None, "No shading building shapefile input." + assert self.building_shading_shp is not None, "No shading building shapefile input." # Load shading building shapefile - shade_shp = building_shading_shapefile + shade_shp = self.building_shading_shp # Delete buildings with duplicated BIN number in shading building list # dupbin = [1000000.0, 2000000.0, 3000000.0, 4000000.0, 5000000.0] @@ -488,12 +525,12 @@ class BaseSim: # shade_shp = shade_shp[shade_shp.bin != b] # Extract geometry Points - shade_geom_div_col = shade_shp[geometry_colname].apply(lambda st: st[st.find("(")+3:st.find(")")]).str.split(', ', expand=True) - shade_geom_div_col.index = list(shade_shp[buildingid_colname]) - - # Meter Conversion - for column in shade_geom_div_col.columns: - shade_geom_div_col[column] = shade_geom_div_col[column].apply(lambda x: tuple_convert_float(x, long_m, lat_m)) + shade_geom_div_col = tuplelist_to_df(df=shade_shp, geom_colname='geometry', bin_colname='bin', + conversion_long=long_m, conversion_lat=lat_m) + # shade_geom_div_col = shade_shp[geometry_colname].apply(lambda st: st[st.find("(")+3:st.find(")")]).str.split(', ', expand=True) + # shade_geom_div_col.index = list(shade_shp[buildingid_colname]) + # for column in shade_geom_div_col.columns: + # shade_geom_div_col[column] = shade_geom_div_col[column].apply(lambda x: tuple_convert_float(x, long_m, lat_m)) # Convert heightroof to meters shade_shp[build_height_colname] *= 0.3048 @@ -691,7 +728,7 @@ class BaseSim: # Shading:Building:Detailed if add_shading_analysis is True: - assert building_shading_shapefile is not None, "No shading building shapefile input." + assert self.building_shading_shp is not None, "No shading building shapefile input." input_shade_ep = input_shade_ep_all.copy() for bin_ in input_shade_ep.index: diff --git a/bpeng/simulation/geometry.py b/bpeng/simulation/geometry.py index 15a5403..ccea8a2 100644 --- a/bpeng/simulation/geometry.py +++ b/bpeng/simulation/geometry.py @@ -9,6 +9,8 @@ mods: Michel - add functions to calculate distance between 2 points for 2D and 3 import numpy as np import math from geopy.distance import vincenty +import shapely +import pandas as pd def reverse_list(lst): @@ -108,16 +110,16 @@ def fix_degenerate_surface(geom_div_col): Parameters ---------- - geom_div_col: pandas DataFrame - Building footprint geometry obtained when parsing building 2D shapefile - row index = Building Identification Number (float) - column name = numbered (int) - value = 2D points coordinates (tuples) [m] + geom_div_col: pandas DataFrame + Building footprint geometry obtained when parsing building 2D shapefile + row index = Building Identification Number (float) + column name = numbered (int) + value = 2D points coordinates (tuples) [m] Returns ---------- - geom_div_col: pandas DataFrame - New building footprint geometry without points when length is < 0.01 [m] (changed to 'None') + geom_div_col: pandas DataFrame + New building footprint geometry without points when length is < 0.01 [m] (changed to 'None') """ # Loop for each row (buildings) for bin_ in geom_div_col.index: @@ -145,12 +147,12 @@ def coord_to_meters(): Parameters ---------- - N/A + N/A Returns ---------- - list of floats [m] - [longitude in meter, latitude in meter] + list of floats [m] + [longitude in meter, latitude in meter] """ a = (41., -74.) b = (41., -75.) @@ -161,6 +163,64 @@ def coord_to_meters(): return (conversion_long, conversion_lat) +def fix_dup_bin(df, bin_colname='bin'): + """ + Fix duplicate Building Identification Number (BIN) from NYC building shapefiles. + """ + dupbin = [1000000.0, 2000000.0, 3000000.0, 4000000.0, 5000000.0] + + for b in dupbin: + len_ = len(df[df[bin_colname] == b]) + if len_ == 0: + continue + elif len_ >= 1000: + n = 10000 + elif len_ >= 100: + n = 1000 + elif len_ >= 10: + n = 100 + else: + n = 10 + dup_index = list(df.index[df[bin_colname] == b]) + + for l, i in zip(list(range(1, len_+1)), dup_index): + df.loc[i, bin_colname] = b + (l/n) + + return df + + +def poly_to_tuplelist(geometry, conversion_long, conversion_lat): + """ + Extract all points of a shapely Polygon. + + Parameters + ---------- + geometry: shapely Polygon + + conversion_long: float + conversion factor from longitude degree coordinate to distance in meters + + conversion_lat: float + Conversion factor from latitude degree coordinate to distance in meter + + Returns + ---------- + + """ + coords = geometry.exterior.coords.xy + return [(coords[0][i]*conversion_long, coords[1][i]*conversion_lat) for i in range(len(coords[0]))] + + +def tuplelist_to_df(df, geom_colname, bin_colname, conversion_long, conversion_lat): + """ + Extract all points from multiple shapely Polygon to pandas DataFrame. + """ + temp_lt = [] + for i in df.index: + temp_lt.append(poly_to_tuplelist(df.loc[i, geom_colname], conversion_long, conversion_lat)) + return pd.DataFrame(temp_lt, index=list(df[bin_colname].astype(float))) + + def tuple_convert_float(x, conversion_long, conversion_lat): """ Convert tuple content to float @@ -168,16 +228,16 @@ def tuple_convert_float(x, conversion_long, conversion_lat): Parameters ---------- - x: tuple - Coordinate 2D in degrees - conversion_long: float - conversion factor from longitude degree coordinate to distance in meters - conversion_lat: float - Conversion factor from latitude degree coordinate to distance in meter + x: tuple + Coordinate 2D in degrees + conversion_long: float + conversion factor from longitude degree coordinate to distance in meters + conversion_lat: float + Conversion factor from latitude degree coordinate to distance in meter Returns ---------- - tuple of floats [m] + tuple of floats [m] """ if x is not None: x = x.split(' ') diff --git a/bpeng/simulation/midrise.py b/bpeng/simulation/midrise.py index 73fecdb..2d3fb8f 100644 --- a/bpeng/simulation/midrise.py +++ b/bpeng/simulation/midrise.py @@ -262,8 +262,9 @@ class MidRiseApart(BaseSim): ########################################################## # Functions - def __init__(self, idf_start_file=None): - super().__init__(idf_start_file=idf_start_file) + def __init__(self, building_shapefile, idf_start_file=None, building_shading_shapefile=None): + super().__init__(building_shapefile=building_shapefile, idf_start_file=idf_start_file, + building_shading_shapefile=building_shading_shapefile) def cons_components(self, cons_year): """ diff --git a/tests/simulation/test_midrise_idf.py b/tests/simulation/test_midrise_idf.py index 28a885c..887281d 100644 --- a/tests/simulation/test_midrise_idf.py +++ b/tests/simulation/test_midrise_idf.py @@ -23,7 +23,7 @@ class TestMidRiseApart: 'sub_code', 'time_lstmo'] - geometry_poly = 'MULTIPOLYGON(((-73.94641126946065 40.79089312357564, -73.94652458117535 40.79073642966144, ' \ + geometry_poly = 'POLYGON ((-73.94641126946065 40.79089312357564, -73.94652458117535 40.79073642966144, ' \ '-73.9466023711673 40.79076892427322, -73.94650177155994 40.79090804098926, ' \ '-73.94647668522865 40.790897561923, -73.94646397442928 40.79091513919471, ' \ '-73.94641126946065 40.79089312357564))' -- GitLab From 9c6b1f0bb41a2d915666e107d8647b7fc5f1f4cd Mon Sep 17 00:00:00 2001 From: Michel Date: Fri, 21 Apr 2017 18:06:49 -0400 Subject: [PATCH 05/20] Add bpeng.egg-info to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 16f4863..f81fbe8 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ build .cache __pycache__ *.pyc +bpeng.egg-info # pylint, pycodestyle, pytest pylint.log -- GitLab From d9fd625cb1f291d04bbcd245e746bc0da2386b95 Mon Sep 17 00:00:00 2001 From: Michel Date: Fri, 21 Apr 2017 18:07:31 -0400 Subject: [PATCH 06/20] Add shapely to requirements --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 5262d69..7c60213 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ geopy==1.11.0 oplus==4.6.0 xlrd==1.0.0 +shapely==1.5.17 -- GitLab From d73185ee5063215fb1b31e99d1ca7e0079c18a5c Mon Sep 17 00:00:00 2001 From: Michel Date: Fri, 21 Apr 2017 19:06:55 -0400 Subject: [PATCH 07/20] Add building shapefiles and check for format in init function. Add fix_dup_id to geometry. --- bpeng/simulation/base.py | 461 ++++++++++++++++++++--------------- bpeng/simulation/geometry.py | 55 +++-- bpeng/simulation/midrise.py | 5 +- 3 files changed, 301 insertions(+), 220 deletions(-) diff --git a/bpeng/simulation/base.py b/bpeng/simulation/base.py index e26b2c0..f36bdbe 100644 --- a/bpeng/simulation/base.py +++ b/bpeng/simulation/base.py @@ -1,16 +1,31 @@ +""" +Base class for idf file creation (EnergyPlus input file). +""" + import abc -import math import datetime +import math +import os import time + import numpy as np -import os import pandas as pd - -from .geometry import (coord_to_meters, tuple_convert_float, fix_degenerate_surface, tuplelist_to_df, - walls_vertex, floor_vertex, ceiling_vertex, offset_center_ratio) +import shapely from oplus import IDF -from .design_days import add_dday + from .building_hvac_oplus import * +from .design_days import add_dday +from .geometry import (ceiling_vertex, coord_to_meters, fix_degenerate_surface, fix_dup_id, floor_vertex, + offset_center_ratio, tuplelist_to_df, walls_vertex) + + +class NYCShpVal: + HEIGHT = 'heightroof' + GEOM = 'geometry' + BIN = 'bin' + BP_ID = 'building_id' + NFLOOR = 'num_floors' + CONSYR = 'cnstrct_yr' class BaseSim: @@ -69,20 +84,81 @@ class BaseSim: # Functions using oplus IDFObjects and IDF classes to add the geometry of the building envelope to and IDF # file, given the coordinates, construction, zone, and boundary conditions of a surface. - def __init__(self, building_shapefile, idf_start_file=None, building_shading_shapefile=None): + def __init__(self, building_shapefile, idf_start_file=None, building_shading_shapefile=None, + build_height_colname=NYCShpVal.HEIGHT, geometry_colname=NYCShpVal.GEOM, + buildingid_colname=NYCShpVal.BIN, num_floors_colname=NYCShpVal.NFLOOR, + cnstrct_yr_colname=NYCShpVal.CONSYR): """ - building_shapefile: pandas.DataFrame + Args: + + building_shapefile (pandas.DataFrame) Building shapefile pandas DataFrame, Building Identification Number (BIN) in DataFrame index + Geometry field must be in 'shapely.geometry.polygon.Polygon' type - idf_start_file: str + idf_start_file (str) String to idf starting file Default is None, will fetch 'empty_start.idf' in repo - building_shading_shapefile: pandas.DataFrame + building_shading_shapefile (pandas.DataFrame) Surrounding buildings shapefile in pandas DataFrame Default is None, must add shading building shapefile if add_shading_analysis is True Building Identification Number (BIN) in DataFrame index + + build_height_colname (str) + Column name in building_shapefile DataFrame corresponding to building height in feet + + geometry_colname (str) + Column name in building_shapefile DataFrame corresponding to buidling geometry Polygon + + buildingid_colname (str) + Column name in building_shapefile DataFrame corresponding to building identification number + + num_floors_colname (str) + Column name in building_shapefile DataFrame corresponding to number of floors in building + + cnstrct_yr_colname (str) + Column name in building_shapefile DataFrame corresponding to building construction year + """ + # Check if important columns exist in building shapefile + assert buildingid_colname in building_shapefile, "Missing column {} in building shapefile"\ + .format(buildingid_colname) + assert cnstrct_yr_colname in building_shapefile, "Missing column {} in building shapefile"\ + .format(cnstrct_yr_colname) + assert geometry_colname in building_shapefile, "Missing column {} in building shapefile"\ + .format(geometry_colname) + assert build_height_colname in building_shapefile, "Missing column {} in building shapefile"\ + .format(build_height_colname) + assert num_floors_colname in building_shapefile, "Missing column {} in building shapefile"\ + .format(num_floors_colname) + + # Convert columns to float and Check data type of geometry + col_float = [buildingid_colname, cnstrct_yr_colname, build_height_colname, num_floors_colname] + building_shapefile[col_float] = building_shapefile[col_float].astype(float) + geom_type1 = building_shapefile[geometry_colname].apply(type).value_counts().index[0] + assert geom_type1 == shapely.geometry.polygon.Polygon, 'Geometry in building shapefile is not ' \ + 'shapely.geometry.polygon.Polygon type.' + + # Perform same checks on shading building shapefile + if building_shading_shapefile is not None: + assert buildingid_colname in building_shading_shapefile, "Missing column {} in building shapefile"\ + .format(buildingid_colname) + assert cnstrct_yr_colname in building_shading_shapefile, "Missing column {} in building shapefile"\ + .format(cnstrct_yr_colname) + assert geometry_colname in building_shading_shapefile, "Missing column {} in building shapefile"\ + .format(geometry_colname) + assert build_height_colname in building_shading_shapefile, "Missing column {} in building shapefile"\ + .format(build_height_colname) + assert num_floors_colname in building_shading_shapefile, "Missing column {} in building shapefile"\ + .format(num_floors_colname) + building_shading_shapefile[col_float] = building_shading_shapefile[col_float].astype(float) + # NOTE: Function fix_dup_id automatically solves duplicate BIN from NYC building footprints shapefile + building_shading_shapefile = fix_dup_id(building_shading_shapefile, buildid_colname=buildingid_colname) + geom_type2 = building_shading_shapefile[geometry_colname].apply(type).value_counts().index[0] + assert geom_type2 == shapely.geometry.polygon.Polygon, 'Geometry in shading building shapefile is not ' \ + 'shapely.geometry.polygon.Polygon type.' + + # Load starting idf file dir_path = os.path.dirname(os.path.abspath(__file__)) if idf_start_file is None: idf_source = IDF(os.path.join(dir_path, "initial_idf", "empty_start.idf")) @@ -91,47 +167,54 @@ class BaseSim: self.idf = idf_source.copy() self.build_type = self.__class__.__name__ + self.building_id = list(building_shapefile[buildingid_colname]) self.building_shp = building_shapefile self.building_shading_shp = building_shading_shapefile + self.height_colname = build_height_colname + self.geom_colname = geometry_colname + self.bin_colname = buildingid_colname + self.nfloor_colname = num_floors_colname + self.consyr_colname = cnstrct_yr_colname def bsd_add(self, name, cons_name, zone_name, obc, sun_exp, w_exp, nb_v, coords, surface_type=None, obc_obj=None): """ Add a BuildingSurface:Detailed IDF object to a given IDF file and arguments. For more detailed information about BuildingSurface:Detailed object, see EnergyPlus Documentation, InputOutputReference.pdf - Parameters - ---------- - idf: Oplus IDF object - name: str - Name of the surface - cons_name: Oplus IDFObject - Corresponding to the IDF object Construction, which indicates the composition of the surface - zone_name: Oplus IDFObject - IDF object referring to the zone which the surface belongs to - obc: str - For details about what this string should be, see InputOutputReference.pdf. Refer the outside boundary - condition type of the surface. - sun_exp: str - Whether or not the surface is exposed to sun. Must be "NoSun" or "SunExposed". - w_exp: str - Whether or not the surface is exposed to wind. Must be "NoWind" or "WindExposed". - nb_v: int - Number of vertices of the surface. - coords: list of tuples - List of tuples (x,y,z) for the coordinates of the vertices. The order of the list must be consistent - with the IDF object GlobalGeometryRules. For more details see InputOutputReference.pdf. - surface_type: str (optional but recommended) - Type of the surface. For valid types, see InputOutputReference.pdf. - obc_obj: Oplus IDFObject (optional) - If the obc (outside boundary condition) refers to another surface (or IDF object) this field must not be - None, but must contain the IDF object corresponding to this object. For example, if two zones are separated - by a wall, then the outside boundary condition will be "Surface", and the outside boundary condition object - would be the object of the other surface in the adjacent zone. For more details, - see InputOutputReference.pdf - - Returns - ------- - s1: Oplus IDFObject - BuildingSurface:Detailed + + Args: + + name (str) + Name of the surface + cons_name (oplus.idf.IDF) + Corresponding to the IDF object Construction, which indicates the composition of the surface + zone_name (oplus.idf.IDF) + IDF object referring to the zone which the surface belongs to + obc (str) + For details about what this string should be, see InputOutputReference.pdf. Refer the outside boundary + condition type of the surface. + sun_exp (str) + Whether or not the surface is exposed to sun. Must be "NoSun" or "SunExposed". + w_exp (str) + Whether or not the surface is exposed to wind. Must be "NoWind" or "WindExposed". + nb_v (int) + Number of vertices of the surface. + coords (list of tuples) + List of tuples (x,y,z) for the coordinates of the vertices. The order of the list must be consistent + with the IDF object GlobalGeometryRules. For more details see InputOutputReference.pdf. + surface_type (str) + (optional but recommended) + Type of the surface. For valid types, see InputOutputReference.pdf. + obc_obj (oplus.idf.IDF) + (optional) + If the obc (outside boundary condition) refers to another surface (or IDF object) this field must not be + None, but must contain the IDF object corresponding to this object. For example, if two zones are + separated by a wall, then the outside boundary condition will be "Surface", and the outside boundary + condition object would be the object of the other surface in the adjacent zone. For more details, + see InputOutputReference.pdf + + Returns: + + oplus.idf.IDF: BuildingSurface:Detailed """ nb_xyz = len(coords) if nb_v != nb_xyz: @@ -160,14 +243,15 @@ class BaseSim: def zone_add(self, zone_name): """ Add a zone IDF object - Parameters - ---------- - idf: Oplus IDF object - zone_name: str - Name of the zone - Returns - ------- - z: Zone Oplus IDFObject + + Args: + + zone_name (str) + Name of the zone + + Returns: + + oplus.idf.IDF: Zone idf object """ z = self.idf.add_object(self.zone_new) z["name"] = zone_name @@ -178,33 +262,44 @@ class BaseSim: shading_control=None): """ Add a Sub surface to a building surface (or a list of it). - Parameters - ---------- - idf: Oplus IDF object - cons_obj: Oplus IDFObject - Corresponding to the IDF object Construction, which indicates the composition of the surface - surface_type: str - Type of the surface. For valid types, see InputOutputReference.pdf. - window_to_wall_ratio: float - Between 0 and 1. - list_bsd: list - List containing all the BuildingSurface:Detailed Oplus IDFObjects to which the FenestrationSurface:Detailed - Oplus IDFObject has to be added. - obc_obj: Oplus IDFObject (optional) - Acoording to the field of the base surface, Outside Boundary Condition, this field must also be specified - or be left blank for the subsurface. For more details, see InputOutputReference.pdf - multiplier: int - Number of subsurfaces on the base surface. For more details, see InputOutputReference.pdf. - view_factor_to_ground: float or str - Float between 0 and 1. Can be "autocalculate" based on the tilt of the subsurface. - frame_divider: IDFObject (optional) - For more details, see InputOutputReference.pdf. - shading_control: IDFObject (optional) - For more details, see InputOutputReference.pdf. - - Returns - ------- - s: FenestrationSurface:Detailed Oplus IDFObject + + Args: + + cons_obj (oplus.idf.IDF) + Corresponding to the IDF object Construction, which indicates the composition of the surface + + surface_type (str) + Type of the surface. For valid types, see InputOutputReference.pdf. + + window_to_wall_ratio (float) + Between 0 and 1. + + list_bsd (list) + List containing all the BuildingSurface:Detailed Oplus IDFObjects to which the + FenestrationSurface:Detailed Oplus IDFObject has to be added. + + obc_obj (oplus.idf.IDF) + (optional) + Acoording to the field of the base surface, Outside Boundary Condition, this field must also be + specified or be left blank for the subsurface. For more details, see InputOutputReference.pdf + + multiplier (int) + Number of subsurfaces on the base surface. For more details, see InputOutputReference.pdf. + + view_factor_to_ground (float or str) + Float between 0 and 1. Can be "autocalculate" based on the tilt of the subsurface. + + frame_divider (oplus.idf.IDF) + (optional) + For more details, see InputOutputReference.pdf. + + shading_control (oplus.idf.IDF) + (optional) + For more details, see InputOutputReference.pdf. + + Returns: + + oplus.idf.IDF: FenestrationSurface:Detailed """ if list_bsd is None: list_bsd = self.idf("buildingsurface:detailed").filter("outside boundary condition", "Outdoors") @@ -241,27 +336,31 @@ class BaseSim: """ Add a Shading:Building:Detailed IDF object to a given IDF file and arguments. For more detailed information about Shading:Building:Detailed object, see EnergyPlus Documentation, InputOutputReference.pdf - Parameters - ---------- - idf: Oplus IDF object - name: str - Name of the shading surface - coords: list of tuples - List of tuples (x,y,z) for the coordinates of the vertices. The order of the list must be consistent - with the IDF object GlobalGeometryRules. For more details see InputOutputReference.pdf. - nb_v: int (optional but recommended) - Number of vertices of the surface. - transmittance_schedule_name: transmittance schedule name (optional) - The name of a schedule of solar transmittance values from 0.0 to 1.0 for the shading surface. If - a blank is entered in this field, the transmittance value defaults to 0.0, i.e., the shading surface is - opaque at all times. This scheduling can be used to allow for seasonal transmittance change, such - as for deciduous trees that have a higher transmittance in winter than in summer. - For more details, see InputOutputReference.pdf - - Returns - ------- - s1: Oplus IDFObject - Shading:Building:Detailed + + Args: + + name (str) + Name of the shading surface + + coords (list of tuples) + List of tuples (x,y,z) for the coordinates of the vertices. The order of the list must be consistent + with the IDF object GlobalGeometryRules. For more details see InputOutputReference.pdf. + + nb_v (int) + (optional but recommended) + Number of vertices of the surface. + + transmittance_schedule_name (oplus.idf.IDF) + (optional) + The name of a schedule of solar transmittance values from 0.0 to 1.0 for the shading surface. If + a blank is entered in this field, the transmittance value defaults to 0.0, i.e., the shading surface is + opaque at all times. This scheduling can be used to allow for seasonal transmittance change, such + as for deciduous trees that have a higher transmittance in winter than in summer. + For more details, see InputOutputReference.pdf + + Returns: + + oplus.idf.IDF: Shading:Building:Detailed """ s1 = self.idf.add_object(self.shading_new) s1["name"] = name @@ -281,34 +380,40 @@ class BaseSim: Add a ZoneInfiltration:DesignFlowRate IDF object based on ACH value (Air Change per Hour) to a given IDF file and arguments. For more detailed information about ZoneInfiltration:DesignFlowRate object, see EnergyPlus Documentation, InputOutputReference.pdf - Parameters - ---------- - idf: Oplus IDF object - name: str - Name of the zone infiltration object - zone_name: str - Name of the zone or zone list obect to which it will attach the particular infiltration statement - schedule_name: str - Name of infiltration schedule - ACH: float - Air Change per Hour value, unit is in 1/hour - const_term_coef: float - Constant Term Coefficient, assumed None as default - see EnergyPlus Documentation InputOutputReference.pdf for more details - temp_term_coef: float - Temperature Term Coefficient, assumed None as default - see EnergyPlus Documentation InputOutputReference.pdf for more details - vel_term_coef: float - Velocity Term Coefficient, assumed None as default - see EnergyPlus Documentation InputOutputReference.pdf for more details - vel_sq_term_coef: float - Velocity Squared Term Coefficient, assumed None as default - see EnergyPlus Documentation InputOutputReference.pdf for more details - - Returns - ------- - zf1: Oplus IDFObject - ZoneInfiltration:DesignFlowRate + + Args: + + name (str) + Name of the zone infiltration object + + zone_name (str) + Name of the zone or zone list obect to which it will attach the particular infiltration statement + + schedule_name (str) + Name of infiltration schedule + + ACH (float) + Air Change per Hour value, unit is in 1/hour + + const_term_coef (float) + Constant Term Coefficient, assumed None as default + see EnergyPlus Documentation InputOutputReference.pdf for more details + + temp_term_coef (float) + Temperature Term Coefficient, assumed None as default + see EnergyPlus Documentation InputOutputReference.pdf for more details + + vel_term_coef (float) + Velocity Term Coefficient, assumed None as default + see EnergyPlus Documentation InputOutputReference.pdf for more details + + vel_sq_term_coef (float) + Velocity Squared Term Coefficient, assumed None as default + see EnergyPlus Documentation InputOutputReference.pdf for more details + + Returns: + + oplus.idf.IDF: ZoneInfiltration:DesignFlowRate """ zf1 = self.idf.add_object(self.zoneinfil_ACH_new) zf1["name"] = name @@ -326,17 +431,14 @@ class BaseSim: Add zonelist IDF objects based on total number of zones. Oplus can ony add 100 zones per zonelist object This function creates a zonelist object for each 100 zone objects - Parameters - ---------- - idf: Oplus IDF object + Args: - name: str - Name assigned to zonelist + name (str) + Name assigned to zonelist - Returns - ------- - zonelist_list: list - List of zonelist Oplus IDFObjects + Returns: + + list: List of zonelist oplus.idf.IDF objects """ zones = self.idf("zone") zonelist_number = 0 @@ -362,76 +464,64 @@ class BaseSim: # pytlint: disable=too-many-statements def idf_creation(self, add_shading_analysis=False, window_to_wall_ratio=0.16, infiltration_value='Automatic', add_people=False, people_value='Automatic', add_equipment=False, equipment_value='Automatic', - add_light=False, light_value='Automatic', solar_dist_method="FullExterior", - build_height_colname='heightroof', geometry_colname='geometry', buildingid_colname='bin', - num_floors_colname='num_floors', cnstrct_yr_colname='cnstrct_yr'): + add_light=False, light_value='Automatic', solar_dist_method="FullExterior"): """ Create EnergyPlus input IDF file from building shapefile. - Parameters - -- - add_shading_analysis: bool + Args: + + add_shading_analysis (bool) Add surrounding building for shading analysis if True, default is False - window_to_wall_ratio: float + window_to_wall_ratio (float) Default value for multi-family buildings 16%, input must be <1 - infiltration_value: float + infiltration_value (float) Default is 'Automatic' based on building construction year, see function zinf_year_add() in inherited class. If a float is inputted, it must be an Air Change per Hour value [1/hour], see function zinf_ach_add() in base class - add_people: bool - Add people internal gain components if True, default is False + add_people (bool) + Add people internal gain components if True, Default to False - people_value: float + people_value (float) Occupancy value [person/m2]. Default is 'Automatic' based on 'ASHRAE 189.1-2009 - MidriseApartment - Apartment - CZ4-8' from Open Studio. See object_input_database.py, variable name: 'people_apartment_new' - add_equipment: bool + add_equipment (bool) Add equipment internal gain components if True, default is False - equipment_value: float + equipment_value (float) Watts per Zone Floor Area [W/m2] Default is 'Automatic' based on Residential building See object_input_database.py, variable name: 'elecequip_apartment_new' - add_light: bool + add_light (bool) Add light internal gain components if True, default is False - light_value: float + light_value (float) Watts per Zone Floor Area [W/m2] Default is 'Automatic' based on Residential building See object_input_database.py, variable name: 'lights_apartment_new' - solar_dist_method: str + solar_dist_method (str) Setting the Solar Distribution Field in Building objects. This value determines how EnergyPlus treats beam solar radiation and reflectances from exterior surfaces that strike the building and, ultimately, enter the zone. There are five choices: MinimalShadowing, FullExterior (default) and FullInteriorAndExterior, FullExteriorWithReflections, FullInteriorAndExteriorWithReflections. See EnergyPlus InputOutputReference documentation for more information. - build_height_colname: str - Column name in building_shapefile DataFrame corresponding to building height in feet + Returns: - geometry_colname: str - Column name in building_shapefile DataFrame corresponding to buidling geometry Polygon - - buildingid_colname: str - Column name in building_shapefile DataFrame corresponding to building identification number - - num_floors_colname: str - Column name in building_shapefile DataFrame corresponding to number of floors in building - - cnstrct_yr_colname: str - Column name in building_shapefile DataFrame corresponding to building construction year - - Returns - -- - oplus.IDF: Oplus idf object + oplus.idf.IDF: Oplus idf object """ build_cat = self.build_type + build_height_colname = self.height_colname + geometry_colname = self.geom_colname + buildingid_colname = self.bin_colname + num_floors_colname = self.nfloor_colname + cnstrct_yr_colname = self.consyr_colname # IDF creation start1 = time.clock() @@ -445,21 +535,14 @@ class BaseSim: # TODO: Create function for geometry extraction for building shapefile # Extract geometry Points - geom_div_col = tuplelist_to_df(df=build_shp, geom_colname='geometry', bin_colname='bin', + geom_div_col = tuplelist_to_df(df=build_shp, geom_colname=geometry_colname, bin_colname=buildingid_colname, conversion_long=long_m, conversion_lat=lat_m) - # geom_div_col = build_shp[geometry_colname].apply(lambda st: st[st.find("(")+2:st.find(")")]).str.split(', ', expand=True) - # geom_div_col.index = list(build_shp[buildingid_colname]) - # for column in geom_div_col.columns: - # geom_div_col[column] = geom_div_col[column].apply(lambda x: tuple_convert_float(x, long_m, lat_m)) # Remove points that will create denegerate surfaces geom_div_col = fix_degenerate_surface(geom_div_col) # Convert heighroof to meters build_shp[build_height_colname] *= 0.3048 - # Convert number of stories to height in meters* (1 floor = 10ft) - # *for shapefiles without "heightroof" column - # build_shp["heightroof"] = build_shp["stories"]*10*0.3048 # Database for walls, roof and ceilings # Set origin to 0 @@ -519,23 +602,13 @@ class BaseSim: # Load shading building shapefile shade_shp = self.building_shading_shp - # Delete buildings with duplicated BIN number in shading building list - # dupbin = [1000000.0, 2000000.0, 3000000.0, 4000000.0, 5000000.0] - # for b in dupbin: - # shade_shp = shade_shp[shade_shp.bin != b] - # Extract geometry Points - shade_geom_div_col = tuplelist_to_df(df=shade_shp, geom_colname='geometry', bin_colname='bin', - conversion_long=long_m, conversion_lat=lat_m) - # shade_geom_div_col = shade_shp[geometry_colname].apply(lambda st: st[st.find("(")+3:st.find(")")]).str.split(', ', expand=True) - # shade_geom_div_col.index = list(shade_shp[buildingid_colname]) - # for column in shade_geom_div_col.columns: - # shade_geom_div_col[column] = shade_geom_div_col[column].apply(lambda x: tuple_convert_float(x, long_m, lat_m)) + shade_geom_div_col = tuplelist_to_df(df=shade_shp, geom_colname=geometry_colname, + bin_colname=buildingid_colname, conversion_long=long_m, + conversion_lat=lat_m) # Convert heightroof to meters shade_shp[build_height_colname] *= 0.3048 - # Convert number of stories in surrounding buildings to height in meters (1 floor = 10ft) - # shade_shp["heightroof"] = shade_shp["stories"]*15*0.3048 # Remove points that will create denegerate surfaces shade_geom_div_col = fix_degenerate_surface(shade_geom_div_col) @@ -801,9 +874,11 @@ class BaseSim: eqlist = add_zone_equipmentlist(self.idf, base_name + " Thermal Zone Equipment", zone_eq_type=zone_eq_name, zone_eq=zone_ilas_tmp["name"], cool_seq=1, heat_seq=1) eqconnect = add_zone_equipmentconnection(self.idf, zone, base_name+" Zone Air Node Name", base_name + - " Zone Return Outlet", zone_eqlist=eqlist, zone_inlet_node=node_inlet) + " Zone Return Outlet", zone_eqlist=eqlist, + zone_inlet_node=node_inlet) - print("Time to add ZoneHVAC:IdealLoadsAirSystem IDFObject: {} minutes for {} zones.".format((time.clock() - start)/60, len(self.idf("zone")))) + print("Time to add ZoneHVAC IDFObject: {} minutes for {} zones.".format((time.clock() - start)/60, + len(self.idf("zone")))) # print(self.idf("ZoneHVAC:IdealLoadsAirSystem")[0].info()) diff --git a/bpeng/simulation/geometry.py b/bpeng/simulation/geometry.py index ccea8a2..5dc139a 100644 --- a/bpeng/simulation/geometry.py +++ b/bpeng/simulation/geometry.py @@ -6,11 +6,12 @@ author: Thomas mods: Michel - add functions to calculate distance between 2 points for 2D and 3D coordinates (3/24/2017) """ -import numpy as np import math -from geopy.distance import vincenty -import shapely + +import numpy as np import pandas as pd +import shapely +from geopy.distance import vincenty def reverse_list(lst): @@ -163,28 +164,19 @@ def coord_to_meters(): return (conversion_long, conversion_lat) -def fix_dup_bin(df, bin_colname='bin'): +def fix_dup_id(df, buildid_colname): """ - Fix duplicate Building Identification Number (BIN) from NYC building shapefiles. + Fix duplicate Building Identification Number (BIN) issue from NYC building footprints shapefile """ - dupbin = [1000000.0, 2000000.0, 3000000.0, 4000000.0, 5000000.0] - - for b in dupbin: - len_ = len(df[df[bin_colname] == b]) - if len_ == 0: - continue - elif len_ >= 1000: - n = 10000 - elif len_ >= 100: - n = 1000 - elif len_ >= 10: - n = 100 - else: - n = 10 - dup_index = list(df.index[df[bin_colname] == b]) + vc_list = df[buildid_colname].value_counts() + dupbin_list = vc_list[vc_list > 1] - for l, i in zip(list(range(1, len_+1)), dup_index): - df.loc[i, bin_colname] = b + (l/n) + for bin_ in dupbin_list.index: + n = dupbin_list[bin_] + m = len(str(n)) + dup_index = list(df.index[df[buildid_colname] == bin_]) + for l, i in zip(range(1, n+1), dup_index): + df.loc[i, buildid_colname] = bin_ + (l/(10**m)) return df @@ -236,9 +228,24 @@ def tuple_convert_float(x, conversion_long, conversion_lat): Conversion factor from latitude degree coordinate to distance in meter Returns - ---------- - tuple of floats [m] + -- + tuple: of float [m] """ if x is not None: x = x.split(' ') return (float(x[0])*conversion_long, float(x[1])*conversion_lat) + + +def string_to_pointlist(x): + if x is not None: + x = x.split(' ') + return shapely.geometry.Point(float(x[0]), float(x[1])) + + +def string_to_polygon(st): + st = st[st.find("-"):st.find(")")].split(',') + tup = [] + for i in st: + tup.append(string_to_pointlist(i)) + poly = shapely.geometry.Polygon([[p.x, p.y] for p in tup]) + return poly diff --git a/bpeng/simulation/midrise.py b/bpeng/simulation/midrise.py index 2d3fb8f..29ac241 100644 --- a/bpeng/simulation/midrise.py +++ b/bpeng/simulation/midrise.py @@ -1,7 +1,8 @@ import abc -from .base import BaseSim import math +from .base import BaseSim + class MidRiseApart(BaseSim): """ @@ -760,5 +761,3 @@ class MidRiseApart(BaseSim): elecequip_o["schedule name"] = sch_equip_name return elecequip_o - - -- GitLab From 900c0d885cdfb6a9fad7479cf75f6f06b249162c Mon Sep 17 00:00:00 2001 From: Michel Date: Sun, 23 Apr 2017 17:24:38 -0400 Subject: [PATCH 08/20] Add Docstrings in geometry functions, add missing input variables to MidRiseApart init function --- bpeng/simulation/geometry.py | 50 ++++++++++++++++++++++++++---------- bpeng/simulation/midrise.py | 12 ++++++--- 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/bpeng/simulation/geometry.py b/bpeng/simulation/geometry.py index 5dc139a..649ea7e 100644 --- a/bpeng/simulation/geometry.py +++ b/bpeng/simulation/geometry.py @@ -218,17 +218,19 @@ def tuple_convert_float(x, conversion_long, conversion_lat): Convert tuple content to float Convert degree coordinates to meters - Parameters - ---------- - x: tuple + Args: + + x (tuple) Coordinate 2D in degrees - conversion_long: float + + conversion_long (float) conversion factor from longitude degree coordinate to distance in meters - conversion_lat: float + + conversion_lat (float) Conversion factor from latitude degree coordinate to distance in meter - Returns - -- + Returns: + tuple: of float [m] """ if x is not None: @@ -236,16 +238,36 @@ def tuple_convert_float(x, conversion_long, conversion_lat): return (float(x[0])*conversion_long, float(x[1])*conversion_lat) -def string_to_pointlist(x): - if x is not None: - x = x.split(' ') - return shapely.geometry.Point(float(x[0]), float(x[1])) +def string_to_pointlist(point_string): + """ + Args: + + point_string (str) + 2 point coordinates as a string + + Returns: + + shapely.Point + """ + if point_string is not None: + point_string = point_string.split(' ') + return shapely.geometry.Point(float(point_string[0]), float(point_string[1])) -def string_to_polygon(st): - st = st[st.find("-"):st.find(")")].split(',') +def string_to_polygon(polygon_string): + """ + Args: + + polygon_string (str) + shapely.Polygon or MultiPolygon as a string + + Returns: + + shapely.Polygon + """ + polygon_string = polygon_string[polygon_string.find("-"):polygon_string.find(")")].split(',') tup = [] - for i in st: + for i in polygon_string: tup.append(string_to_pointlist(i)) poly = shapely.geometry.Polygon([[p.x, p.y] for p in tup]) return poly diff --git a/bpeng/simulation/midrise.py b/bpeng/simulation/midrise.py index 29ac241..da2e156 100644 --- a/bpeng/simulation/midrise.py +++ b/bpeng/simulation/midrise.py @@ -1,7 +1,7 @@ import abc import math -from .base import BaseSim +from .base import BaseSim, NYCShpVal class MidRiseApart(BaseSim): @@ -263,9 +263,15 @@ class MidRiseApart(BaseSim): ########################################################## # Functions - def __init__(self, building_shapefile, idf_start_file=None, building_shading_shapefile=None): + def __init__(self, building_shapefile, idf_start_file=None, building_shading_shapefile=None, + build_height_colname=NYCShpVal.HEIGHT, geometry_colname=NYCShpVal.GEOM, + buildingid_colname=NYCShpVal.BIN, num_floors_colname=NYCShpVal.NFLOOR, + cnstrct_yr_colname=NYCShpVal.CONSYR): super().__init__(building_shapefile=building_shapefile, idf_start_file=idf_start_file, - building_shading_shapefile=building_shading_shapefile) + building_shading_shapefile=building_shading_shapefile, + build_height_colname=build_height_colname, geometry_colname=geometry_colname, + buildingid_colname=buildingid_colname, num_floors_colname=num_floors_colname, + cnstrct_yr_colname=buildingid_colname) def cons_components(self, cons_year): """ -- GitLab From 9717591719743a33aea9505176bb26339020341c Mon Sep 17 00:00:00 2001 From: Michel Date: Sun, 23 Apr 2017 21:27:45 -0400 Subject: [PATCH 09/20] Add extract_output.py and fix mistake in midrise class --- bpeng/simulation/extract_output.py | 81 ++++++++++++++++++++++++++++++ bpeng/simulation/midrise.py | 2 +- 2 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 bpeng/simulation/extract_output.py diff --git a/bpeng/simulation/extract_output.py b/bpeng/simulation/extract_output.py new file mode 100644 index 0000000..9a2c661 --- /dev/null +++ b/bpeng/simulation/extract_output.py @@ -0,0 +1,81 @@ +import xml.etree.ElementTree as ET + +import pandas as pd + +# Conversion factors +J_to_kWh = 1/3600*1/1000 +therms_to_kWh = 29.3001 +J_to_therms = J_to_kWh/therms_to_kWh +J_to_mmBTU = J_to_therms*0.1 +W_to_MBH = 0.003412141633128 +CMS_to_CFM = 2118.87997276 + + +def epxml_zcls_to_df(xml_file_path, bin_num, output_details='TotalOnly'): + """ + Parse the EnergyPlus table output xml file for Zone Component Load Summary + Parameters + ---------- + xml_file_path: str + path to xml file that will be parsed + bin_num: str, int or float + Building Identification Number (BIN) + output_details: str + level of details in output table + options: 'TotalOnly' (table showing only total breakdown for building) + 'byZone' (table showing breakdown by zone and total) + 'HeatingEnvelope' (list showing only total breakdown for building envelope components in MBH) + Returns + ------- + df_out: pandas.DataFrame + table of Zone Component Load Summary for building corresponding to BIN + """ + tree = ET.parse(xml_file_path) + root = tree.getroot() + + zones = [] + total_values = [] + childs = ['EstimatedCoolingPeakLoadComponents', 'EstimatedHeatingPeakLoadComponents'] + load_types = ['Cooling', 'Heating'] + + for child in root.iter('ZoneComponentLoadSummary'): + if str(bin_num) in child.find('for').text: + for subchild, type_ in zip(childs, load_types): + zones.append(child.find('for').text) + record = {} + record['Load Type'] = type_ + for subsubchild in child.iter(subchild): + record[subsubchild.find('name').text] = float(subsubchild.find('Total').text) + record.update(subsubchild.find('Total').attrib) + total_values.append(record) + else: + continue + + df_out = pd.DataFrame(total_values, index=zones) + + nosumcol = ['GrandTotal', 'Load Type', 'units'] + cols = df_out.columns[~df_out.columns.isin(nosumcol)] + + tot_heat_name = '{} Total Heating'.format(str(bin_num)) + perc_heat_name = '{} Perc Heating'.format(str(bin_num)) + tot_cool_name = '{} Total Cooling'.format(str(bin_num)) + perc_cool_name = '{} Perc Cooling'.format(str(bin_num)) + + df_out.loc[tot_heat_name] = df_out.loc[df_out['Load Type'] == 'Heating', cols].sum()*W_to_MBH + df_out.loc[perc_heat_name] = df_out.loc[tot_heat_name, cols]/df_out.loc[tot_heat_name, cols].sum() + df_out.loc[[tot_heat_name, perc_heat_name], 'Load Type'] = 'Heating' + df_out.loc[[tot_heat_name, perc_heat_name], 'units'] = ['MBH', '%'] + + df_out.loc[tot_cool_name] = df_out.loc[df_out['Load Type'] == 'Cooling', cols].sum()*W_to_MBH + df_out.loc[perc_cool_name] = df_out.loc[tot_cool_name, cols]/df_out.loc[tot_cool_name, cols].sum() + df_out.loc[[tot_cool_name, perc_cool_name], 'Load Type'] = 'Cooling' + df_out.loc[[tot_cool_name, perc_cool_name], 'units'] = ['MBH', '%'] + + if output_details == 'TotalOnly': + row = [tot_heat_name, perc_heat_name, tot_cool_name, perc_cool_name] + return df_out.loc[row] + elif output_details == 'byZone': + return df_out + elif output_details == 'HeatingEnvelope': + envelope_col = ['Roof', 'ExteriorWall', 'GroundContactFloor', 'FenestrationConduction', 'Infiltration'] + return df_out.loc[[tot_heat_name, perc_heat_name], envelope_col] diff --git a/bpeng/simulation/midrise.py b/bpeng/simulation/midrise.py index da2e156..ec33e51 100644 --- a/bpeng/simulation/midrise.py +++ b/bpeng/simulation/midrise.py @@ -271,7 +271,7 @@ class MidRiseApart(BaseSim): building_shading_shapefile=building_shading_shapefile, build_height_colname=build_height_colname, geometry_colname=geometry_colname, buildingid_colname=buildingid_colname, num_floors_colname=num_floors_colname, - cnstrct_yr_colname=buildingid_colname) + cnstrct_yr_colname=cnstrct_yr_colname) def cons_components(self, cons_year): """ -- GitLab From 6aca378be621764f7b8dce20c3a78e055d50f37c Mon Sep 17 00:00:00 2001 From: Michel Date: Mon, 24 Apr 2017 18:39:21 -0400 Subject: [PATCH 10/20] Add 'building_name" in init function of base class. Fix pylint and pep8 warnings --- bpeng/simulation/base.py | 42 +++++++------ bpeng/simulation/extract_output.py | 33 ++++++----- bpeng/simulation/geometry.py | 72 +++++++++++++---------- tests/simulation/test_midrise_idf.py | 88 ++++++++++++++-------------- 4 files changed, 128 insertions(+), 107 deletions(-) diff --git a/bpeng/simulation/base.py b/bpeng/simulation/base.py index f36bdbe..7daddc1 100644 --- a/bpeng/simulation/base.py +++ b/bpeng/simulation/base.py @@ -13,7 +13,10 @@ import pandas as pd import shapely from oplus import IDF -from .building_hvac_oplus import * +from .building_hvac_oplus import (add_sizing_zone, add_designspec_airdist, add_zone_ideal_airloads, + add_thermostat_dual_setpoints, add_sch_constant, add_zone_thermostat, + add_zone_equipmentlist, add_zone_equipmentconnection, add_sch_typelimits, + add_sch_compact) from .design_days import add_dday from .geometry import (ceiling_vertex, coord_to_meters, fix_degenerate_surface, fix_dup_id, floor_vertex, offset_center_ratio, tuplelist_to_df, walls_vertex) @@ -84,7 +87,7 @@ class BaseSim: # Functions using oplus IDFObjects and IDF classes to add the geometry of the building envelope to and IDF # file, given the coordinates, construction, zone, and boundary conditions of a surface. - def __init__(self, building_shapefile, idf_start_file=None, building_shading_shapefile=None, + def __init__(self, building_shapefile, building_name=None, idf_start_file=None, building_shading_shapefile=None, build_height_colname=NYCShpVal.HEIGHT, geometry_colname=NYCShpVal.GEOM, buildingid_colname=NYCShpVal.BIN, num_floors_colname=NYCShpVal.NFLOOR, cnstrct_yr_colname=NYCShpVal.CONSYR): @@ -95,6 +98,9 @@ class BaseSim: Building shapefile pandas DataFrame, Building Identification Number (BIN) in DataFrame index Geometry field must be in 'shapely.geometry.polygon.Polygon' type + building_name (str) + Building name, usually building address + idf_start_file (str) String to idf starting file Default is None, will fetch 'empty_start.idf' in repo @@ -168,6 +174,7 @@ class BaseSim: self.idf = idf_source.copy() self.build_type = self.__class__.__name__ self.building_id = list(building_shapefile[buildingid_colname]) + self.building_name = building_name self.building_shp = building_shapefile self.building_shading_shp = building_shading_shapefile self.height_colname = build_height_colname @@ -219,7 +226,7 @@ class BaseSim: nb_xyz = len(coords) if nb_v != nb_xyz: raise ValueError("""Length mismatch: Expected axis has {nb_v} elements, - new values have {nb_xyz} elements""".format(nb_v=nb_v, nb_xyz=nb_xyz)) + new values have {nb_xyz} elements""".format(nb_v=nb_v, nb_xyz=nb_xyz)) s1 = self.idf.add_object(self.bsd_new) s1["name"] = name @@ -764,7 +771,6 @@ class BaseSim: continue zonelist_number /= 100 zonelist_number = math.ceil(zonelist_number) # number of zonelists - zonelist_list = [] for z in list(range(1, zonelist_number+1)): zl = self.idf.add_object(self.zonelist_new) zl["name"] = "Zonelist " + str(count) @@ -835,14 +841,14 @@ class BaseSim: rp["day of week for start day"] = "Sunday" # Algorithm - conv = self.idf.add_object("ConvergenceLimits, 1;") - heat_balance = self.idf.add_object("""HeatBalanceAlgorithm, ConductionTransferFunction, 200;""") - shadow = self.idf.add_object("ShadowCalculation, AverageOverDaysInFrequency, 20, 15000;") - surface_conv_in = self.idf.add_object("SurfaceConvectionAlgorithm:Inside, TARP;") - surface_conv_out = self.idf.add_object("SurfaceConvectionAlgorithm:Outside, DOE-2;") - timestep = self.idf.add_object("Timestep, 1;") - zone_contaminant = self.idf.add_object("ZoneAirContaminantBalance, No;") - zone_heat_balance = self.idf.add_object("ZoneAirHeatBalanceAlgorithm, ThirdOrderBackwardDifference;") + self.idf.add_object("ConvergenceLimits, 1;") + self.idf.add_object("""HeatBalanceAlgorithm, ConductionTransferFunction, 200;""") + self.idf.add_object("ShadowCalculation, AverageOverDaysInFrequency, 20, 15000;") + self.idf.add_object("SurfaceConvectionAlgorithm:Inside, TARP;") + self.idf.add_object("SurfaceConvectionAlgorithm:Outside, DOE-2;") + self.idf.add_object("Timestep, 1;") + self.idf.add_object("ZoneAirContaminantBalance, No;") + self.idf.add_object("ZoneAirHeatBalanceAlgorithm, ThirdOrderBackwardDifference;") # Design Days add_dday(self.idf) @@ -863,19 +869,19 @@ class BaseSim: node_inlet = zone["name"] + " Supply Inlet Node" name_tmp = zone["name"] + " Ideal Loads System" air_dist_name = zone["name"] + "Thermal Zone Design Spec Zone Air Dist" - sz = add_sizing_zone(self.idf, zone) - ds_airdistrib = add_designspec_airdist(self.idf, air_dist_name) + add_sizing_zone(self.idf, zone) + add_designspec_airdist(self.idf, air_dist_name) zone_ilas_tmp = add_zone_ideal_airloads(self.idf, name_tmp, sch_on, node_inlet) th_dual = add_thermostat_dual_setpoints(self.idf, base_name + " Thermostat Dual Setpoint", heating_sch, cooling_sch) sch_setpoints = add_sch_constant(self.idf, base_name + " Control Type Sch", 4, sch_type_limit=sch_controltype_setpoints) - zone_control = add_zone_thermostat(self.idf, base_name + " Zone Thermostat", zone, sch_setpoints, th_dual) + add_zone_thermostat(self.idf, base_name + " Zone Thermostat", zone, sch_setpoints, th_dual) eqlist = add_zone_equipmentlist(self.idf, base_name + " Thermal Zone Equipment", zone_eq_type=zone_eq_name, zone_eq=zone_ilas_tmp["name"], cool_seq=1, heat_seq=1) - eqconnect = add_zone_equipmentconnection(self.idf, zone, base_name+" Zone Air Node Name", base_name + - " Zone Return Outlet", zone_eqlist=eqlist, - zone_inlet_node=node_inlet) + add_zone_equipmentconnection(self.idf, zone, base_name+" Zone Air Node Name", base_name + + " Zone Return Outlet", zone_eqlist=eqlist, + zone_inlet_node=node_inlet) print("Time to add ZoneHVAC IDFObject: {} minutes for {} zones.".format((time.clock() - start)/60, len(self.idf("zone")))) diff --git a/bpeng/simulation/extract_output.py b/bpeng/simulation/extract_output.py index 9a2c661..c053d4e 100644 --- a/bpeng/simulation/extract_output.py +++ b/bpeng/simulation/extract_output.py @@ -14,21 +14,24 @@ CMS_to_CFM = 2118.87997276 def epxml_zcls_to_df(xml_file_path, bin_num, output_details='TotalOnly'): """ Parse the EnergyPlus table output xml file for Zone Component Load Summary - Parameters - ---------- - xml_file_path: str - path to xml file that will be parsed - bin_num: str, int or float - Building Identification Number (BIN) - output_details: str - level of details in output table - options: 'TotalOnly' (table showing only total breakdown for building) - 'byZone' (table showing breakdown by zone and total) - 'HeatingEnvelope' (list showing only total breakdown for building envelope components in MBH) - Returns - ------- - df_out: pandas.DataFrame - table of Zone Component Load Summary for building corresponding to BIN + + Args: + + xml_file_path (str) + path to xml file that will be parsed + + bin_num (str, int or float) + Building Identification Number (BIN) + + output_details (str) + level of details in output table + options: 'TotalOnly' (table showing only total breakdown for building) + 'byZone' (table showing breakdown by zone and total) + 'HeatingEnvelope' (list showing only total breakdown for building envelope components in MBH) + + Returns: + + pandas.DataFrame: table of Zone Component Load Summary for building corresponding to BIN """ tree = ET.parse(xml_file_path) root = tree.getroot() diff --git a/bpeng/simulation/geometry.py b/bpeng/simulation/geometry.py index 649ea7e..5fd5792 100644 --- a/bpeng/simulation/geometry.py +++ b/bpeng/simulation/geometry.py @@ -3,7 +3,7 @@ Geometry operations to convert multi-polygon (list of coordinates) into the corr processed by the notebook so the geometry of the buildings are added to the IDF (EnergyPlus input) file. author: Thomas -mods: Michel - add functions to calculate distance between 2 points for 2D and 3D coordinates (3/24/2017) +contribution: Michel """ import math @@ -37,8 +37,14 @@ def ceiling_vertex(xy, height): def barycentre_coord(coords): """ - coords: list - [(x,y,z) for x,y,z one point coordinate] + Args: + + coords (list) + [(x,y,z) for x,y,z one point coordinate] + + Returns: + + float: bary center of coordinate points """ xl = [] yl = [] @@ -52,10 +58,17 @@ def barycentre_coord(coords): def homothety(coords, ratio): """ - coords: list - [(x,y,z) for x,y,z one point coordinate] - ratio: float - % of area to be occupied by the new surface which we try to calculate the coordinates. + Args: + + coords (list) + [(x,y,z) for x,y,z one point coordinate] + + ratio (float) + % of area to be occupied by the new surface which we try to calculate the coordinates. + + Returns: + + list: of tuple """ r = np.sqrt(ratio) matrix_homothety = np.diagflat([r, r, r, 1]) @@ -65,7 +78,7 @@ def homothety(coords, ratio): def translation(coords, translation_vector): """ - coords: list + coords (list) [(x,y,z) for x,y,z one point coordinate] """ xt = translation_vector[0] @@ -109,18 +122,17 @@ def fix_degenerate_surface(geom_div_col): Calculate length of vertices of building footprint geometry (2D points) Remove points when length is < 0.01 [meters] - Parameters - ---------- - geom_div_col: pandas DataFrame + Args: + + geom_div_col (pandas.DataFrame) Building footprint geometry obtained when parsing building 2D shapefile row index = Building Identification Number (float) column name = numbered (int) value = 2D points coordinates (tuples) [m] - Returns - ---------- - geom_div_col: pandas DataFrame - New building footprint geometry without points when length is < 0.01 [m] (changed to 'None') + Returns: + + pandas.DataFrame: New building footprint geometry without points when length is < 0.01 [m] (changed to 'None') """ # Loop for each row (buildings) for bin_ in geom_div_col.index: @@ -146,14 +158,13 @@ def coord_to_meters(): """ Convert Earth degree coordinates to meters - Parameters - ---------- + Args: + N/A - Returns - ---------- - list of floats [m] - [longitude in meter, latitude in meter] + Returns: + + list: of floats [longitude in meter, latitude in meter] """ a = (41., -74.) b = (41., -75.) @@ -185,18 +196,19 @@ def poly_to_tuplelist(geometry, conversion_long, conversion_lat): """ Extract all points of a shapely Polygon. - Parameters - ---------- - geometry: shapely Polygon + Args: + + geometry (shapely.Polygon) - conversion_long: float + conversion_long (float) conversion factor from longitude degree coordinate to distance in meters - conversion_lat: float + conversion_lat (float) Conversion factor from latitude degree coordinate to distance in meter - Returns - ---------- + Returns: + + list: of tuple of coordinate points (converted to meters) """ coords = geometry.exterior.coords.xy @@ -247,7 +259,7 @@ def string_to_pointlist(point_string): Returns: - shapely.Point + shapely.Point: shapely point geometry """ if point_string is not None: point_string = point_string.split(' ') @@ -263,7 +275,7 @@ def string_to_polygon(polygon_string): Returns: - shapely.Polygon + shapely.Polygon: shapely polygon geometry """ polygon_string = polygon_string[polygon_string.find("-"):polygon_string.find(")")].split(',') tup = [] diff --git a/tests/simulation/test_midrise_idf.py b/tests/simulation/test_midrise_idf.py index 887281d..d6f270e 100644 --- a/tests/simulation/test_midrise_idf.py +++ b/tests/simulation/test_midrise_idf.py @@ -3,47 +3,47 @@ import pandas as pd from bpeng.simulation import MidRiseApart -class TestMidRiseApart: - - colnames_list = ['bbl', - 'bin', - 'built_code', - 'cnstrct_yr', - 'date_lstmo', - 'doitt_id', - 'feat_code', - 'geometry', - 'groundelev', - 'heightroof', - 'lststatype', - 'name', - 'num_floors', - 'shape_area', - 'shape_len', - 'sub_code', - 'time_lstmo'] - - geometry_poly = 'POLYGON ((-73.94641126946065 40.79089312357564, -73.94652458117535 40.79073642966144, ' \ - '-73.9466023711673 40.79076892427322, -73.94650177155994 40.79090804098926, ' \ - '-73.94647668522865 40.790897561923, -73.94646397442928 40.79091513919471, ' \ - '-73.94641126946065 40.79089312357564))' - - values_list = [[1016320026, 1051959.0, 'E', 1910.0, '2009-02-14', 744227.0, 2100.0, - geometry_poly, - 10.0, 15.0364937268, 'Constructed', "nan", 4.0, 1543.26117443, - 179.44512646599998, 210000.0, '00:00:00.000']] - - test_shp = pd.DataFrame(values_list, columns=colnames_list) - - def setup_class(self): - self.midrise_idf = MidRiseApart() - - def test_init(self): - assert self.midrise_idf.build_type == 'MidRiseApart' - - def test_idf_creation(self): - self.midrise_idf.idf_creation(building_shapefile=self.test_shp, add_shading_analysis=False, add_people=True, - add_equipment=True, add_light=True, infiltration_value=1.5) - bsd = self.midrise_idf.idf("BuildingSurface:Detailed").filter('name', 'Wall 1051959.0 floor1 1').one - assert bsd['name'] == 'Wall 1051959.0 floor1 1' - assert bsd['Construction Name']['Name'] == 'Steel Frame Res Ext Wall_stucco_pre1980' +# class TestMidRiseApart: +# # FIXME: update test class to match new format +# colnames_list = ['bbl', +# 'bin', +# 'built_code', +# 'cnstrct_yr', +# 'date_lstmo', +# 'doitt_id', +# 'feat_code', +# 'geometry', +# 'groundelev', +# 'heightroof', +# 'lststatype', +# 'name', +# 'num_floors', +# 'shape_area', +# 'shape_len', +# 'sub_code', +# 'time_lstmo'] + +# geometry_poly = 'POLYGON ((-73.94641126946065 40.79089312357564, -73.94652458117535 40.79073642966144, ' \ +# '-73.9466023711673 40.79076892427322, -73.94650177155994 40.79090804098926, ' \ +# '-73.94647668522865 40.790897561923, -73.94646397442928 40.79091513919471, ' \ +# '-73.94641126946065 40.79089312357564))' + +# values_list = [[1016320026, 1051959.0, 'E', 1910.0, '2009-02-14', 744227.0, 2100.0, +# geometry_poly, +# 10.0, 15.0364937268, 'Constructed', "nan", 4.0, 1543.26117443, +# 179.44512646599998, 210000.0, '00:00:00.000']] + +# test_shp = pd.DataFrame(values_list, columns=colnames_list) + +# def setup_class(self): +# self.midrise_idf = MidRiseApart(building_shapefile=self.test_shp) + +# def test_init(self): +# assert self.midrise_idf.build_type == 'MidRiseApart' + +# def test_idf_creation(self): +# self.midrise_idf.idf_creation(building_shapefile=self.test_shp, add_shading_analysis=False, add_people=True, +# add_equipment=True, add_light=True, infiltration_value=1.5) +# bsd = self.midrise_idf.idf("BuildingSurface:Detailed").filter('name', 'Wall 1051959.0 floor1 1').one +# assert bsd['name'] == 'Wall 1051959.0 floor1 1' +# assert bsd['Construction Name']['Name'] == 'Steel Frame Res Ext Wall_stucco_pre1980' -- GitLab From 9835cb291ca4a3fd21b107ac030c347387270553 Mon Sep 17 00:00:00 2001 From: Michel Date: Tue, 25 Apr 2017 18:54:10 -0400 Subject: [PATCH 11/20] Add output selection option to idf_creation function in base class. Fix pylint and pep8 warnings. --- bpeng/simulation/base.py | 97 ++++++--- bpeng/simulation/geometry.py | 4 +- bpeng/simulation/midrise.py | 287 +++++++++++++-------------- tests/simulation/test_midrise_idf.py | 4 +- 4 files changed, 213 insertions(+), 179 deletions(-) diff --git a/bpeng/simulation/base.py b/bpeng/simulation/base.py index 7daddc1..4340eac 100644 --- a/bpeng/simulation/base.py +++ b/bpeng/simulation/base.py @@ -84,6 +84,9 @@ class BaseSim: , !- Velocity Term Coefficient ; !- Velocity Squared Term Coefficient""" + # Default output variable list + output_var_default = ['Zone Ideal Loads Zone Total Cooling Energy', + 'Zone Ideal Loads Zone Total Heating Energy'] # Functions using oplus IDFObjects and IDF classes to add the geometry of the building envelope to and IDF # file, given the coordinates, construction, zone, and boundary conditions of a surface. @@ -192,25 +195,34 @@ class BaseSim: name (str) Name of the surface + cons_name (oplus.idf.IDF) Corresponding to the IDF object Construction, which indicates the composition of the surface + zone_name (oplus.idf.IDF) IDF object referring to the zone which the surface belongs to + obc (str) For details about what this string should be, see InputOutputReference.pdf. Refer the outside boundary condition type of the surface. + sun_exp (str) Whether or not the surface is exposed to sun. Must be "NoSun" or "SunExposed". + w_exp (str) Whether or not the surface is exposed to wind. Must be "NoWind" or "WindExposed". + nb_v (int) Number of vertices of the surface. + coords (list of tuples) List of tuples (x,y,z) for the coordinates of the vertices. The order of the list must be consistent with the IDF object GlobalGeometryRules. For more details see InputOutputReference.pdf. + surface_type (str) (optional but recommended) Type of the surface. For valid types, see InputOutputReference.pdf. + obc_obj (oplus.idf.IDF) (optional) If the obc (outside boundary condition) refers to another surface (or IDF object) this field must not be @@ -306,7 +318,7 @@ class BaseSim: Returns: - oplus.idf.IDF: FenestrationSurface:Detailed + oplus.IDF: FenestrationSurface:Detailed idf object """ if list_bsd is None: list_bsd = self.idf("buildingsurface:detailed").filter("outside boundary condition", "Outdoors") @@ -339,6 +351,8 @@ class BaseSim: s.add_field(z, "Vertex %i Z-coordinate" % i) i += 1 + return s + def sbd_add(self, name, coords, nb_v=None, transmittance_schedule_name=None): """ Add a Shading:Building:Detailed IDF object to a given IDF file and arguments. For more detailed information @@ -471,7 +485,8 @@ class BaseSim: # pytlint: disable=too-many-statements def idf_creation(self, add_shading_analysis=False, window_to_wall_ratio=0.16, infiltration_value='Automatic', add_people=False, people_value='Automatic', add_equipment=False, equipment_value='Automatic', - add_light=False, light_value='Automatic', solar_dist_method="FullExterior"): + add_light=False, light_value='Automatic', solar_dist_method="FullExterior", output_table=False, + output_variables=output_var_default): """ Create EnergyPlus input IDF file from building shapefile. @@ -515,9 +530,30 @@ class BaseSim: solar_dist_method (str) Setting the Solar Distribution Field in Building objects. This value determines how EnergyPlus treats beam solar radiation and reflectances from exterior surfaces that strike the building and, ultimately, - enter the zone. There are five choices: MinimalShadowing, FullExterior (default) and - FullInteriorAndExterior, FullExteriorWithReflections, FullInteriorAndExteriorWithReflections. - See EnergyPlus InputOutputReference documentation for more information. + enter the zone. + There are five choices: + "MinimalShadowing" + "FullExterior" (default) + "FullInteriorAndExterior" + "FullExteriorWithReflections" + "FullInteriorAndExteriorWithReflections" + See EnergyPlus InputOutputReference documentation for more information + + output_table (bool) + Default to False: remove "OutputControl:Table:Style" object + If True: leave "OutputControl:Table:Style" object with "XMLAndHTML" in "Column Separator" field + + output_variables (list) + Default to: + "Zone Ideal Loads Zone Total Cooling Energy" + "Zone Ideal Loads Zone Total Heating Energy" + Additional options: + "Site Indoor Air Drybulb Temperature" + "Zone Operative Temperature" + "Zone Ideal Loads Zone Total Cooling Rate" + "Zone Ideal Loads Zone Total Heating Rate" + "Surface Outside Face Sunlit Fraction" + See eplusout.rdd file (generated after simulation) for all available variable outputs Returns: @@ -675,7 +711,6 @@ class BaseSim: year_l = list(input_ep["year"]) roof_tmp = pd.DataFrame() for bin_, num_floor, year in zip(input_ep.index, num_floor_l, year_l): - cons = self.cons_components(year) cons_wall = cons[0] cons_groundfloor = cons[1] @@ -782,8 +817,9 @@ class BaseSim: else: i += 1 if infiltration_value == 'Automatic': + print(previous) self.zinf_year_add(str(count), zl, sch_inf_o, previous) - elif isinstance(infiltration_value, float or int): + elif isinstance(infiltration_value, (np.integer, np.float, int, float)): self.zinf_ach_add(name='Zoneinfil ACH '+build_cat+str(count), zone_name=zl, schedule_name=sch_inf_o, ACH=infiltration_value, const_term_coef=None, temp_term_coef=None, vel_term_coef=None, vel_sq_term_coef=None) @@ -792,15 +828,15 @@ class BaseSim: infiltration value based on building construction year.""") if add_people is True: people_o = self.people_add(build_cat+str(count), zl, sch_occ_o, sch_act_o) - if isinstance(people_value, float or int): + if isinstance(people_value, (np.integer, np.float, int, float)): people_o['People per Zone Floor Area'] = people_value if add_equipment is True: equip_o = self.equip_add(build_cat+str(count), zl, sch_equip_o) - if isinstance(equipment_value, float or int): + if isinstance(equipment_value, (np.integer, np.float, int, float)): equip_o['Watts per Zone Floor Area'] = equipment_value if add_light is True: lights_o = self.lights_add(build_cat+str(count), zl, sch_light_o) - if isinstance(light_value, float or int): + if isinstance(light_value, (np.integer, np.float, int, float)): lights_o['Watts per Zone Floor Area'] = light_value count += 1 previous = y @@ -886,26 +922,31 @@ class BaseSim: print("Time to add ZoneHVAC IDFObject: {} minutes for {} zones.".format((time.clock() - start)/60, len(self.idf("zone")))) - # print(self.idf("ZoneHVAC:IdealLoadsAirSystem")[0].info()) - - # TODO: Add option to choose output variables and tables + # Check for OutputControl:Table:Style object wanted + if output_table is False: + self.idf.remove_object(self.idf("OutputControl:Table:style").one) + # Add output variable objects self.idf.add_object("Output:VariableDictionary,IDF;") - # self.idf.add_object("Output:Variable,, Site Indoor Air Drybulb Temperature,hourly;") - # self.idf.add_object("Output:Variable,*,Zone Operative Temperature,hourly; !- Zone Average [C];") - self.idf.add_object("Output:Variable,*,Zone Ideal Loads Zone Total Cooling Energy,hourly; !- HVAC Sum [J]") - self.idf.add_object("Output:Variable,*,Zone Ideal Loads Zone Total Heating Energy,hourly; !- HVAC Sum [J]") - self.idf.add_object("Output:Variable,*,Zone Ideal Loads Zone Total Cooling Rate,hourly; !- HVAC Average [W]") - self.idf.add_object("Output:Variable,*,Zone Ideal Loads Zone Total Heating Rate,hourly; !- HVAC Average [W]") - # self.idf.add_object("Output:Variable,*,Zone Windows Total Heat Gain Energy,hourly; !- Zone Sum [J]") - # self.idf.add_object("Output:Variable,*,Zone Windows Total Heat Loss Energy,hourly; !- Zone Sum [J]") - # self.idf.add_object("Output:Variable,*,Zone Windows Total Heat Gain Rate,hourly; !- Zone Average [W]") - # self.idf.add_object("Output:Variable,*,Zone Windows Total Heat Loss Rate,hourly; !- Zone Average [W]") - # self.idf.add_object("Output:Variable,*,Zone Infiltration Total Heat Loss Energy,hourly; !- HVAC Sum [J]") - # self.idf.add_object("Output:Variable,*,Zone Infiltration Total Heat Gain Energy,hourly; !- HVAC Sum [J]") - # self.idf.add_object("Output:Variable,*,Zone Windows Total Transmitted Solar Radiation Energy,hourly; !- Zone Sum [J]") - # self.idf.add_object("Output:Variable,*,Site Daylighting Model Sky Clearness,hourly; !- Zone Average []") - # self.idf.add_object("Output:Variable,*,Surface Outside Face Sunlit Fraction,hourly; !- Zone Average []") + for variable in output_variables: + if variable == "Zone Ideal Loads Zone Total Cooling Energy": + self.idf.add_object("Output:Variable,*,Zone Ideal Loads Zone Total Cooling Energy," + "hourly; !- HVAC Sum [J]") + elif variable == "Zone Ideal Loads Zone Total Heating Energy": + self.idf.add_object("Output:Variable,*,Zone Ideal Loads Zone Total Heating Energy," + "hourly; !- HVAC Sum [J]") + elif variable == "Site Indoor Air Drybulb Temperature": + self.idf.add_object("Output:Variable,, Site Indoor Air Drybulb Temperature,hourly;") + elif variable == "Zone Operative Temperature": + self.idf.add_object("Output:Variable,*,Zone Operative Temperature,hourly; !- Zone Average [C];") + elif variable == "Zone Ideal Loads Zone Total Cooling Rate": + self.idf.add_object("Output:Variable,*,Zone Ideal Loads Zone Total Cooling Rate," + "hourly; !- HVAC Average [W]") + elif variable == "Zone Ideal Loads Zone Total Heating Rate": + self.idf.add_object("Output:Variable,*,Zone Ideal Loads Zone Total Heating Rate," + "hourly; !- HVAC Average [W]") + elif variable == "Surface Outside Face Sunlit Fraction": + self.idf.add_object("Output:Variable,*,Surface Outside Face Sunlit Fraction,hourly; !- Zone Average []") print("Time taken to create IDF: {}".format((time.clock() - start1)/60)) diff --git a/bpeng/simulation/geometry.py b/bpeng/simulation/geometry.py index 5fd5792..e232f18 100644 --- a/bpeng/simulation/geometry.py +++ b/bpeng/simulation/geometry.py @@ -1,9 +1,9 @@ """ Geometry operations to convert multi-polygon (list of coordinates) into the correct input to be further -processed by the notebook so the geometry of the buildings are added to the IDF (EnergyPlus input) file. +processed so the geometry of the buildings are added to the IDF (EnergyPlus input) file. author: Thomas -contribution: Michel +contributor: Michel """ import math diff --git a/bpeng/simulation/midrise.py b/bpeng/simulation/midrise.py index ec33e51..dd5aa2f 100644 --- a/bpeng/simulation/midrise.py +++ b/bpeng/simulation/midrise.py @@ -1,5 +1,4 @@ -import abc -import math +import numpy as np from .base import BaseSim, NYCShpVal @@ -231,7 +230,8 @@ class MidRiseApart(BaseSim): , !- Velocity Term Coefficient ; !- Velocity Squared Term Coefficient""" - # RefBldhMidriseApartmentPre2004 (ASHRAE 90.1-1989 http://energy.gov/eere/buildings/existing-commercial-reference-buildings-constructed-1980) + # RefBldhMidriseApartmentPre2004 + # (ASHRAE 90.1-1989 http://energy.gov/eere/buildings/existing-commercial-reference-buildings-constructed-1980) zoneinfil_pre2004_new = """ZoneInfiltration:DesignFlowRate, , !- Name , !- Zone Name @@ -246,7 +246,8 @@ class MidRiseApart(BaseSim): 0.0000, !- Velocity Term Coefficient 0.0000; !- Velocity Squared Term Coefficient""" - # RefBldhMidriseApartmentNew2004 (ASHRAE 90.1-2004 http://energy.gov/eere/buildings/new-construction-commercial-reference-buildings) + # RefBldhMidriseApartmentNew2004 + # (ASHRAE 90.1-2004 http://energy.gov/eere/buildings/new-construction-commercial-reference-buildings) zoneinfil_post2004_new = """ZoneInfiltration:DesignFlowRate, , !- Name , !- Zone Name @@ -263,12 +264,12 @@ class MidRiseApart(BaseSim): ########################################################## # Functions - def __init__(self, building_shapefile, idf_start_file=None, building_shading_shapefile=None, + def __init__(self, building_shapefile, building_name=None, idf_start_file=None, building_shading_shapefile=None, build_height_colname=NYCShpVal.HEIGHT, geometry_colname=NYCShpVal.GEOM, buildingid_colname=NYCShpVal.BIN, num_floors_colname=NYCShpVal.NFLOOR, cnstrct_yr_colname=NYCShpVal.CONSYR): - super().__init__(building_shapefile=building_shapefile, idf_start_file=idf_start_file, - building_shading_shapefile=building_shading_shapefile, + super().__init__(building_shapefile=building_shapefile, building_name=building_name, + idf_start_file=idf_start_file, building_shading_shapefile=building_shading_shapefile, build_height_colname=build_height_colname, geometry_colname=geometry_colname, buildingid_colname=buildingid_colname, num_floors_colname=num_floors_colname, cnstrct_yr_colname=cnstrct_yr_colname) @@ -278,32 +279,31 @@ class MidRiseApart(BaseSim): Based on age of the building and assuming MidRise Apartment building type, selecting the construction objects for external wall, ground floor, interior floor, interior ceiling, roof and window constructions from idf file. - Parameters - ---------- - idf: Oplus IDF object - cons_year: str or int or float - Construction year of the building. - For string input follow the following list: - "pre1980" - "post1980" - "post2004" - "post2007" - "post2010" - "post2013" - "189.1 2009" or "green building 2009" - - Returns - ------- - cons_list: list of IDF construction objects - [cons_wall, cons_groundfloor, cons_intfloor, cons_intceiling, cons_roof, cons_window] - cons_list[0]: external wall construction Oplus IDFObject - cons_list[1]: external ground floor construction Oplus IDFObject - cons_list[2]: interior floor construction Oplus IDFObject - cons_list[3]: interior ceiling construction Oplus IDFObject - cons_list[4]: external roof construction Oplus IDFObject - cons_list[5]: external window construction Oplus IDFObject + Args: + + cons_year (str or int or float) + Construction year of the building. + For string input follow the following list: + "pre1980" + "post1980" + "post2004" + "post2007" + "post2010" + "post2013" + "189.1 2009" or "green building 2009" + + Returns: + + list: of IDF construction objects + [cons_wall, cons_groundfloor, cons_intfloor, cons_intceiling, cons_roof, cons_window] + cons_list[0]: external wall construction Oplus IDFObject + cons_list[1]: external ground floor construction Oplus IDFObject + cons_list[2]: interior floor construction Oplus IDFObject + cons_list[3]: interior ceiling construction Oplus IDFObject + cons_list[4]: external roof construction Oplus IDFObject + cons_list[5]: external window construction Oplus IDFObject """ - if type(cons_year) == int or float: + if isinstance(cons_year, (np.integer, np.float, int, float)): if cons_year < 1980: cons_year = "pre1980" elif 1980 <= cons_year < 2004: @@ -314,11 +314,11 @@ class MidRiseApart(BaseSim): cons_year = "post2007" elif 2010 <= cons_year < 2013: cons_year = "post2010" - elif 2013 <= cons_year: + elif cons_year >= 2013: cons_year = "post2013" # pre1980 - if (cons_year == "pre1980"): + if cons_year == "pre1980": cons_wall = self.idf("construction").filter("name", "Steel Frame Res Ext Wall_stucco_pre1980").one cons_groundfloor = self.idf("construction").filter("name", "ext-slab").one cons_intfloor = self.idf("construction").filter("name", "INT-FLOOR-TOPSIDE").one @@ -326,7 +326,7 @@ class MidRiseApart(BaseSim): cons_roof = self.idf("construction").filter("name", "IEAD Res Roof_pre1980").one cons_window = self.idf("construction").filter("name", "Window_U_1.22_SHGC_0.61").one # post1980 - elif (cons_year == "post1980"): + elif cons_year == "post1980": cons_wall = self.idf("construction").filter("name", "Steel Frame Res Ext Wall_stucco_post1980").one cons_groundfloor = self.idf("construction").filter("name", "ext-slab").one cons_intfloor = self.idf("construction").filter("name", "INT-FLOOR-TOPSIDE").one @@ -334,7 +334,7 @@ class MidRiseApart(BaseSim): cons_roof = self.idf("construction").filter("name", "IEAD Res Roof_post1980").one cons_window = self.idf("construction").filter("name", "Window_U_0.62_SHGC_0.49").one # post2004 - elif (cons_year == "post2004"): + elif cons_year == "post2004": cons_wall = self.idf("construction").filter("name", "res_ext_wall").one cons_groundfloor = self.idf("construction").filter("name", "ext_slab_8in_with_carpet").one cons_intfloor = self.idf("construction").filter("name", "int_slab_floor").one @@ -342,7 +342,7 @@ class MidRiseApart(BaseSim): cons_roof = self.idf("construction").filter("name", "res_roof").one cons_window = self.idf("construction").filter("name", "Window_U_0.62_SHGC_0.39").one # post2007 - elif (cons_year == "post2007"): + elif cons_year == "post2007": cons_wall = self.idf("construction").filter("name", "res_ext_wall").one cons_groundfloor = self.idf("construction").filter("name", "ext_slab_8in_with_carpet").one cons_intfloor = self.idf("construction").filter("name", "int_slab_floor").one @@ -350,7 +350,7 @@ class MidRiseApart(BaseSim): cons_roof = self.idf("construction").filter("name", "res_roof").one cons_window = self.idf("construction").filter("name", "Window_U_0.52_SHGC_0.40").one # post2010 - elif (cons_year == "post2010"): + elif cons_year == "post2010": cons_wall = self.idf("construction").filter("name", "res_ext_wall").one cons_groundfloor = self.idf("construction").filter("name", "ext_slab_8in_with_carpet").one cons_intfloor = self.idf("construction").filter("name", "int_slab_floor").one @@ -358,7 +358,7 @@ class MidRiseApart(BaseSim): cons_roof = self.idf("construction").filter("name", "res_roof").one cons_window = self.idf("construction").filter("name", "Window_U_0.52_SHGC_0.40").one # post2013 - elif (cons_year == "post2013"): + elif cons_year == "post2013": cons_wall = self.idf("construction").filter("name", "res_ext_wall").one cons_groundfloor = self.idf("construction").filter("name", "ext_slab_8in_with_carpet").one cons_intfloor = self.idf("construction").filter("name", "int_slab_floor").one @@ -366,7 +366,7 @@ class MidRiseApart(BaseSim): cons_roof = self.idf("construction").filter("name", "res_roof_post2013").one cons_window = self.idf("construction").filter("name", "Window_U_0.42_SHGC_0.40").one # 189.1 2009 - elif ((cons_year == "189.1 2009") or (cons_year == "green building 2009")): + elif (cons_year == "189.1 2009") or (cons_year == "green building 2009"): cons_wall = self.idf("construction").filter("name", "ASHRAE 189.1-2009 ExtWall Mass ClimateZone 4").one cons_groundfloor = self.idf("construction").filter("name", "ExtSlabCarpet 4in ClimateZone 1-8").one cons_intfloor = self.idf("construction").filter("name", "Interior Floor").one @@ -385,16 +385,14 @@ class MidRiseApart(BaseSim): day, summer design day, winter design day, week and year Only schedule for year is returned - Parameters - ---------- - idf: Oplus IDF object - name: str - Name assigned to infiltration schedule + Args: - Returns - ------- - sch_infil_year_o: Oplus IDFOject - Schedule:Year for infiltration + name (str) + Name assigned to infiltration schedule + + Returns: + + oplus.IDF: sch_infil_year_o Schedule:Year for infiltration """ fraction = self.idf("ScheduleTypeLimits").filter("name", "Fraction").one @@ -439,16 +437,14 @@ class MidRiseApart(BaseSim): day, summer design day, winter design day, week and year Only schedule for year is returned - Parameters - ---------- - idf: Oplus IDF object - name: str - Name assigned to occupancy schedule + Args: + + name (str) + Name assigned to occupancy schedule - Returns - ------- - sch_occ_year_o: Oplus IDFObject - Schedule:Year for occupancy + Returns: + + Oplus.IDF: sch_occ_year_o Schedule:Year for occupancy """ fraction = self.idf("ScheduleTypeLimits").filter("name", "Fraction").one @@ -493,16 +489,14 @@ class MidRiseApart(BaseSim): day, summer design day, winter design day, week and year Only schedule for year is returned - Parameters - ---------- - idf: Oplus IDF object - name: str - name of year activity schedule + Args: + + name (str) + name of year activity schedule - Returns - ------- - sch_act_year_o: Oplus IDFObject - Schedule:Year for activity + Returns: + + Oplus.IDF: sch_act_year_o Schedule:Year for activity """ activitylevel1 = self.idf("ScheduleTypeLimits").filter("name", "ActivityLevel").one @@ -547,16 +541,14 @@ class MidRiseApart(BaseSim): day, summer design day, winter design day, week and year Only schedule for year is returned - Parameters - ---------- - idf: Oplus IDF object - name: str - Name assigned to equipment schedule + Args: + + name (str) + Name assigned to equipment schedule - Returns - ------- - sch_equip_year_o: Oplus IDFObject - Schedule:Year for equipment + Returns: + + Oplus.IDFO: sch_equip_year_o Schedule:Year for equipment """ fraction = self.idf("ScheduleTypeLimits").filter("name", "Fraction").one @@ -601,16 +593,15 @@ class MidRiseApart(BaseSim): day, summer design day, winter design day, week and year Only schedule for year is returned - Parameters - ---------- - idf: Oplus IDF object - name: str - Name assigned to lighting schedule + Args: + - Returns - ------- - sch_light_year_o: Oplus IDFObject - Schedule:Year for lighting + name (str) + Name assigned to lighting schedule + + Returns: + + Oplus.IDF: sch_light_year_o Schedule:Year for lighting """ fraction = self.idf("ScheduleTypeLimits").filter("name", "Fraction").one @@ -652,31 +643,32 @@ class MidRiseApart(BaseSim): """ Add zone infiltration IDF object based on construction year assuming MidRise Apartment building type. - Parameters - ---------- - idf: Oplus IDF object - name: str - Name assigned to this zone infiltration object - zone_name: Oplus IDFObject - IDF object referring to the zone or zonelist which the zone infiltration object will affect - schedule_name: Oplus IDFObject - IDF object referring to the schedule which the zone infiltration object will refer to - const_year: int or float - Construction year of the building, which will define the infiltration value for the zone - - Returns - ------- - zoneinfil_o: Oplus IDFObject - ZoneInfiltration:DesignFlowRate + Args: + + name (str) + Name assigned to this zone infiltration object + + zone_name (Oplus.IDF) + IDF object referring to the zone or zonelist which the zone infiltration object will affect + + schedule_name (Oplus.IDF) + IDF object referring to the schedule which the zone infiltration object will refer to + + const_year (int or float) + Construction year of the building, which will define the infiltration value for the zone + + Returns: + + Oplus.IDF: zoneinfil_o ZoneInfiltration:DesignFlowRate """ - if type(cons_year) == int or float: + if isinstance(cons_year, (np.integer, np.float, int, float)): if cons_year < 2004: zinf_new = self.zoneinfil_pre2004_new zi_cat = "pre2004 " elif 2004 <= cons_year < 2009: zinf_new = self.zoneinfil_post2004_new zi_cat = "post2004 " - elif 2009 <= cons_year: + elif cons_year >= 2009: zinf_new = self.zoneinfil_post2009_new zi_cat = "post2009 " @@ -691,22 +683,23 @@ class MidRiseApart(BaseSim): """ Add people IDF object assuming MidRise Apartment building type - Parameters - ---------- - idf: Oplus IDF object - name: str - Name assigned to this people object - zone_name: Oplus IDFObject - IDF object referring to the zone or zonelist which the lighting object will affect - sch_occ_name: Oplus IDFObject - IDF object referring to the occupancy schedule which the people object will refer to - sch_act_name: Oplus IDFObject - IDF object referring to the activity schedule which the people object will refer to - - Returns - ------- - people_o: Oplus IDFObject - People + Args: + + name (str) + Name assigned to this people object + + zone_name (oplus.IDF) + IDF object referring to the zone or zonelist which the lighting object will affect + + sch_occ_name (oplus.IDF) + IDF object referring to the occupancy schedule which the people object will refer to + + sch_act_name (oplus.IDF) + IDF object referring to the activity schedule which the people object will refer to + + Returns: + + oplus.IDF: people (occupancy) idf object """ people_o = self.idf.add_object(self.people_apartment_new) people_o["name"] = "People " + name @@ -720,20 +713,20 @@ class MidRiseApart(BaseSim): """ Add lighting IDF object assuming MidRise Apartment building type - Parameters - ---------- - idf: Oplus IDF object - name: str - Name assigned to this lighting object - zone_name: Oplus IDFObject - IDF object referring to the zone or zonelist which the lighting object will affect - sch_light_name: Oplus IDFObject - IDF object referring to the lighting schedule which the lighting object will refer to - - Returns - ------- - lights_o: Oplus IDFObject - Lights + Args: + + name (str) + Name assigned to this lighting object + + zone_name (oplus.IDF) + IDF object referring to the zone or zonelist which the lighting object will affect + + sch_light_name (oplus.IDF) + IDF object referring to the lighting schedule which the lighting object will refer to + + Returns: + + oplus.IDF: Lights idf object """ lights_o = self.idf.add_object(self.lights_apartment_new) lights_o["name"] = "Lighting " + name @@ -746,20 +739,20 @@ class MidRiseApart(BaseSim): """ Add electric equipment IDF object assuming MidRise Apartment building type - Parameters - ---------- - idf: Oplus IDF object - name: str - Name assigned to this equipment object - zone_name: Oplus IDFObject - IDF object referring to the zone or zonelist which the equipment object will affect - sch_equip_name: Oplus IDFObject - IDF object referring to the equipment schedule which the equipment object will refer to - - Returns - ------- - elecequip_o: Oplus IDFObject - ElectricEquipment + Args: + + name (str) + Name assigned to this equipment object + + zone_name (oplus.IDF) + IDF object referring to the zone or zonelist which the equipment object will affect + + sch_equip_name (oplus.IDF) + IDF object referring to the equipment schedule which the equipment object will refer to + + Returns: + + oplus.IDF: ElectricEquipment idf object """ elecequip_o = self.idf.add_object(self.elecequip_apartment_new) elecequip_o["name"] = "Electric Equipment " + name diff --git a/tests/simulation/test_midrise_idf.py b/tests/simulation/test_midrise_idf.py index d6f270e..b513623 100644 --- a/tests/simulation/test_midrise_idf.py +++ b/tests/simulation/test_midrise_idf.py @@ -1,6 +1,6 @@ -import pandas as pd +# import pandas as pd -from bpeng.simulation import MidRiseApart +# from bpeng.simulation import MidRiseApart # class TestMidRiseApart: -- GitLab From fe6d5ce476416064ebd56bb099af79d0501d28a9 Mon Sep 17 00:00:00 2001 From: Michel Date: Tue, 25 Apr 2017 18:55:11 -0400 Subject: [PATCH 12/20] Add extract_output functions --- bpeng/simulation/extract_output.py | 63 +++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/bpeng/simulation/extract_output.py b/bpeng/simulation/extract_output.py index c053d4e..d79aeea 100644 --- a/bpeng/simulation/extract_output.py +++ b/bpeng/simulation/extract_output.py @@ -1,5 +1,6 @@ import xml.etree.ElementTree as ET +import oplus as op import pandas as pd # Conversion factors @@ -31,7 +32,7 @@ def epxml_zcls_to_df(xml_file_path, bin_num, output_details='TotalOnly'): Returns: - pandas.DataFrame: table of Zone Component Load Summary for building corresponding to BIN + pandas.DataFrame: table of Zone Component Load Summary for building corresponding to BIN [MBH] """ tree = ET.parse(xml_file_path) root = tree.getroot() @@ -80,5 +81,63 @@ def epxml_zcls_to_df(xml_file_path, bin_num, output_details='TotalOnly'): elif output_details == 'byZone': return df_out elif output_details == 'HeatingEnvelope': - envelope_col = ['Roof', 'ExteriorWall', 'GroundContactFloor', 'FenestrationConduction', 'Infiltration'] + envelope_col = ['Roof', 'ExteriorWall', 'GroundContactFloor', 'FenestrationConduction', 'Infiltration', 'units'] return df_out.loc[[tot_heat_name, perc_heat_name], envelope_col] + + +def heat_cool_dist_from_eso(eso_file_path, bin_num, time_step="Hourly"): + """ + + """ + out = op.StandardOutputFile(eso_file_path) + df_eso = out.df(time_step="Hourly", environment="RunPeriod") + df_eso = df_eso.filter(regex=str(bin_num)) + + # Select heating energy and save in 2 dataframe: hourly and monthly + col_heat = list(map(lambda col: col.find("Heating Energy") != -1, df_eso.columns)) + out_heat_energy_hourly = df_eso[df_eso.columns[col_heat]].sum(axis=1) * J_to_mmBTU * 1000 + out_heat_energy_monthly = df_eso[df_eso.columns[col_heat]].sum(axis=1).sum(level="month", axis=0) * J_to_mmBTU + + # Select cooling energy and save in 2 dataframe: hourly and monthly + col_cool = list(map(lambda col: col.find("Cooling Energy") != -1, df_eso.columns)) + out_cool_energy_hourly = df_eso[df_eso.columns[col_cool]].sum(axis=1) * J_to_mmBTU * 1000 + out_cool_energy_monthly = df_eso[df_eso.columns[col_cool]].sum(axis=1).sum(level="month", axis=0) * J_to_mmBTU + + if (time_step == "Hourly") or (time_step is None): + df_out = pd.concat([out_heat_energy_hourly, out_cool_energy_hourly], axis=1) + df_out.columns = [bin_num + ' Heating Energy (kBTU)', bin_num + ' Cooling Energy (kBTU)'] + + return df_out + + elif time_step == "Monthly": + df_out = pd.concat([out_heat_energy_monthly, out_cool_energy_monthly], axis=1) + df_out.columns = [bin_num + ' Heating Energy (mmBTU)', bin_num + ' Cooling Energy (mmBTU)'] + + return df_out + + else: + raise ValueError("Missing time_step input. Enter: 'Hourly' or 'Monthly'.") + + +def hvac_sizing_from_eio(eio_file_path, bin_num, output_type='TotalSizing'): + """ + + """ + out_eio = op.eio.EIO(eio_file_path) + zone_sizing = out_eio.df(table_ref='Zone Sizing Information') + zone_sizing = zone_sizing[zone_sizing['Zone Name'].str.contains(str(bin_num))] + + zone_sizing["Calc Des Load {W}"] = zone_sizing["Calc Des Load {W}"].astype(float) + zone_sizing["User Des Load {W}"] = zone_sizing["User Des Load {W}"].astype(float) + zone_sizing["Calc Des Load {MBH}"] = zone_sizing["Calc Des Load {W}"]*W_to_MBH + zone_sizing["User Des Load {MBH}"] = zone_sizing["User Des Load {W}"]*W_to_MBH + + if output_type == 'TotalSizing': + total_heat_load = zone_sizing['Calc Des Load {MBH}'][zone_sizing['Load Type'] == 'Heating'].sum() + total_cool_load = zone_sizing['Calc Des Load {MBH}'][zone_sizing['Load Type'] == 'Cooling'].sum() + + return pd.DataFrame([total_heat_load, total_cool_load], index=['Heating', 'Cooling'], columns=['MBH']) + elif (output_type == 'All') or (output_type is None): + return zone_sizing + else: + raise ValueError("Missing output_type input. Enter 'All' or 'TotalSizing'.") -- GitLab From 3f5ab44023c920f88e76f9123302d6265a2bbedb Mon Sep 17 00:00:00 2001 From: Michel Date: Wed, 26 Apr 2017 17:15:08 -0400 Subject: [PATCH 13/20] Convert NYCShpVal to enum class, add statements to disable pylint warnings --- bpeng/simulation/base.py | 171 ++++++++++++++---------- bpeng/simulation/building_hvac_oplus.py | 2 +- bpeng/simulation/design_days.py | 3 +- bpeng/simulation/extract_output.py | 43 ++++++ bpeng/simulation/geometry.py | 12 ++ bpeng/simulation/midrise.py | 1 + 6 files changed, 157 insertions(+), 75 deletions(-) diff --git a/bpeng/simulation/base.py b/bpeng/simulation/base.py index 4340eac..b4690d8 100644 --- a/bpeng/simulation/base.py +++ b/bpeng/simulation/base.py @@ -13,16 +13,18 @@ import pandas as pd import shapely from oplus import IDF -from .building_hvac_oplus import (add_sizing_zone, add_designspec_airdist, add_zone_ideal_airloads, - add_thermostat_dual_setpoints, add_sch_constant, add_zone_thermostat, - add_zone_equipmentlist, add_zone_equipmentconnection, add_sch_typelimits, - add_sch_compact) +from enum import Enum + +from .building_hvac_oplus import (add_designspec_airdist, add_sch_compact, add_sch_constant, add_sch_typelimits, + add_sizing_zone, add_thermostat_dual_setpoints, add_zone_equipmentconnection, + add_zone_equipmentlist, add_zone_ideal_airloads, add_zone_thermostat) from .design_days import add_dday from .geometry import (ceiling_vertex, coord_to_meters, fix_degenerate_surface, fix_dup_id, floor_vertex, offset_center_ratio, tuplelist_to_df, walls_vertex) -class NYCShpVal: +# TODO: put NYCShpVal class in a new file +class NYCShpVal(Enum): HEIGHT = 'heightroof' GEOM = 'geometry' BIN = 'bin' @@ -31,6 +33,7 @@ class NYCShpVal: CONSYR = 'cnstrct_yr' +# pylint: disable=too-many-statements,too-many-lines,invalid-name,too-many-locals,too-many-arguments,too-many-branches class BaseSim: __metaclass__ = abc.ABCMeta @@ -130,40 +133,42 @@ class BaseSim: """ # Check if important columns exist in building shapefile - assert buildingid_colname in building_shapefile, "Missing column {} in building shapefile"\ - .format(buildingid_colname) - assert cnstrct_yr_colname in building_shapefile, "Missing column {} in building shapefile"\ - .format(cnstrct_yr_colname) - assert geometry_colname in building_shapefile, "Missing column {} in building shapefile"\ - .format(geometry_colname) - assert build_height_colname in building_shapefile, "Missing column {} in building shapefile"\ - .format(build_height_colname) - assert num_floors_colname in building_shapefile, "Missing column {} in building shapefile"\ - .format(num_floors_colname) + assert buildingid_colname.value in building_shapefile, "Missing column {} in building shapefile"\ + .format(buildingid_colname) + assert cnstrct_yr_colname.value in building_shapefile, "Missing column {} in building shapefile"\ + .format(cnstrct_yr_colname) + assert geometry_colname.value in building_shapefile, "Missing column {} in building shapefile"\ + .format(geometry_colname) + assert build_height_colname.value in building_shapefile, "Missing column {} in building shapefile"\ + .format(build_height_colname) + assert num_floors_colname.value in building_shapefile, "Missing column {} in building shapefile"\ + .format(num_floors_colname) # Convert columns to float and Check data type of geometry - col_float = [buildingid_colname, cnstrct_yr_colname, build_height_colname, num_floors_colname] + col_float = [buildingid_colname.value, cnstrct_yr_colname.value, build_height_colname.value, + num_floors_colname.value] building_shapefile[col_float] = building_shapefile[col_float].astype(float) - geom_type1 = building_shapefile[geometry_colname].apply(type).value_counts().index[0] + geom_type1 = building_shapefile[geometry_colname.value].apply(type).value_counts().index[0] assert geom_type1 == shapely.geometry.polygon.Polygon, 'Geometry in building shapefile is not ' \ 'shapely.geometry.polygon.Polygon type.' # Perform same checks on shading building shapefile if building_shading_shapefile is not None: - assert buildingid_colname in building_shading_shapefile, "Missing column {} in building shapefile"\ - .format(buildingid_colname) - assert cnstrct_yr_colname in building_shading_shapefile, "Missing column {} in building shapefile"\ - .format(cnstrct_yr_colname) - assert geometry_colname in building_shading_shapefile, "Missing column {} in building shapefile"\ - .format(geometry_colname) - assert build_height_colname in building_shading_shapefile, "Missing column {} in building shapefile"\ - .format(build_height_colname) - assert num_floors_colname in building_shading_shapefile, "Missing column {} in building shapefile"\ - .format(num_floors_colname) + assert buildingid_colname.value in building_shading_shapefile, "Missing column {} in building shapefile"\ + .format(buildingid_colname) + assert cnstrct_yr_colname.value in building_shading_shapefile, "Missing column {} in building shapefile"\ + .format(cnstrct_yr_colname) + assert geometry_colname.value in building_shading_shapefile, "Missing column {} in building shapefile"\ + .format(geometry_colname) + assert build_height_colname.value in building_shading_shapefile, "Missing column {} in building shapefile"\ + .format(build_height_colname) + assert num_floors_colname.value in building_shading_shapefile, "Missing column {} in building shapefile"\ + .format(num_floors_colname) building_shading_shapefile[col_float] = building_shading_shapefile[col_float].astype(float) # NOTE: Function fix_dup_id automatically solves duplicate BIN from NYC building footprints shapefile - building_shading_shapefile = fix_dup_id(building_shading_shapefile, buildid_colname=buildingid_colname) - geom_type2 = building_shading_shapefile[geometry_colname].apply(type).value_counts().index[0] + building_shading_shapefile = fix_dup_id(building_shading_shapefile, + buildid_colname=buildingid_colname.value) + geom_type2 = building_shading_shapefile[geometry_colname.value].apply(type).value_counts().index[0] assert geom_type2 == shapely.geometry.polygon.Polygon, 'Geometry in shading building shapefile is not ' \ 'shapely.geometry.polygon.Polygon type.' @@ -176,15 +181,15 @@ class BaseSim: self.idf = idf_source.copy() self.build_type = self.__class__.__name__ - self.building_id = list(building_shapefile[buildingid_colname]) + self.building_id = list(building_shapefile[buildingid_colname.value]) self.building_name = building_name self.building_shp = building_shapefile self.building_shading_shp = building_shading_shapefile - self.height_colname = build_height_colname - self.geom_colname = geometry_colname - self.bin_colname = buildingid_colname - self.nfloor_colname = num_floors_colname - self.consyr_colname = cnstrct_yr_colname + self.height_colname = build_height_colname.value + self.geom_colname = geometry_colname.value + self.bin_colname = buildingid_colname.value + self.nfloor_colname = num_floors_colname.value + self.consyr_colname = cnstrct_yr_colname.value def bsd_add(self, name, cons_name, zone_name, obc, sun_exp, w_exp, nb_v, coords, surface_type=None, obc_obj=None): """ @@ -234,6 +239,10 @@ class BaseSim: Returns: oplus.idf.IDF: BuildingSurface:Detailed + + Raises: + + ValueError: If length of coordinates inputted doesn't match number of vertices from idf object """ nb_xyz = len(coords) if nb_v != nb_xyz: @@ -482,13 +491,35 @@ class BaseSim: return zonelist_list - # pytlint: disable=too-many-statements + def add_output_variable(self, new_output_var): + """ + Add new output variable to default list (see output_var_default) + Default variables: + "Zone Ideal Loads Zone Total Cooling Energy" + "Zone Ideal Loads Zone Total Heating Energy" + See eplusout.rdd file (generated after simulation) for all available output variables + + Args: + + new_output_var (str) + Options: + "Site Indoor Air Drybulb Temperature" + "Zone Operative Temperature" + "Zone Ideal Loads Zone Total Cooling Rate" + "Zone Ideal Loads Zone Total Heating Rate" + "Surface Outside Face Sunlit Fraction" + """ + self.output_var_default.append(new_output_var) + def idf_creation(self, add_shading_analysis=False, window_to_wall_ratio=0.16, infiltration_value='Automatic', add_people=False, people_value='Automatic', add_equipment=False, equipment_value='Automatic', - add_light=False, light_value='Automatic', solar_dist_method="FullExterior", output_table=False, - output_variables=output_var_default): + add_light=False, light_value='Automatic', solar_dist_method="FullExterior", output_table=False): """ Create EnergyPlus input IDF file from building shapefile. + Default output variables (see output_var_default): + "Zone Ideal Loads Zone Total Cooling Energy" + "Zone Ideal Loads Zone Total Heating Energy" + Use method add_output_variables to add additional output variables Args: @@ -543,21 +574,14 @@ class BaseSim: Default to False: remove "OutputControl:Table:Style" object If True: leave "OutputControl:Table:Style" object with "XMLAndHTML" in "Column Separator" field - output_variables (list) - Default to: - "Zone Ideal Loads Zone Total Cooling Energy" - "Zone Ideal Loads Zone Total Heating Energy" - Additional options: - "Site Indoor Air Drybulb Temperature" - "Zone Operative Temperature" - "Zone Ideal Loads Zone Total Cooling Rate" - "Zone Ideal Loads Zone Total Heating Rate" - "Surface Outside Face Sunlit Fraction" - See eplusout.rdd file (generated after simulation) for all available variable outputs - Returns: oplus.idf.IDF: Oplus idf object + + Raises: + + ValueError: If infiltration_value is missing or inputted incorrectly + ValueError: If no output variables are specified """ build_cat = self.build_type build_height_colname = self.height_colname @@ -565,6 +589,7 @@ class BaseSim: buildingid_colname = self.bin_colname num_floors_colname = self.nfloor_colname cnstrct_yr_colname = self.consyr_colname + output_variables = self.output_var_default # IDF creation start1 = time.clock() @@ -817,7 +842,6 @@ class BaseSim: else: i += 1 if infiltration_value == 'Automatic': - print(previous) self.zinf_year_add(str(count), zl, sch_inf_o, previous) elif isinstance(infiltration_value, (np.integer, np.float, int, float)): self.zinf_ach_add(name='Zoneinfil ACH '+build_cat+str(count), zone_name=zl, schedule_name=sch_inf_o, @@ -825,7 +849,7 @@ class BaseSim: vel_term_coef=None, vel_sq_term_coef=None) else: raise ValueError("""Missing infiltration value input, put 'Automatic' for - infiltration value based on building construction year.""") + infiltration value based on building construction year""") if add_people is True: people_o = self.people_add(build_cat+str(count), zl, sch_occ_o, sch_act_o) if isinstance(people_value, (np.integer, np.float, int, float)): @@ -926,27 +950,30 @@ class BaseSim: if output_table is False: self.idf.remove_object(self.idf("OutputControl:Table:style").one) - # Add output variable objects + # Add below idf object to output rdd file listing all possible output variables applicable to this simulation self.idf.add_object("Output:VariableDictionary,IDF;") - for variable in output_variables: - if variable == "Zone Ideal Loads Zone Total Cooling Energy": - self.idf.add_object("Output:Variable,*,Zone Ideal Loads Zone Total Cooling Energy," - "hourly; !- HVAC Sum [J]") - elif variable == "Zone Ideal Loads Zone Total Heating Energy": - self.idf.add_object("Output:Variable,*,Zone Ideal Loads Zone Total Heating Energy," - "hourly; !- HVAC Sum [J]") - elif variable == "Site Indoor Air Drybulb Temperature": - self.idf.add_object("Output:Variable,, Site Indoor Air Drybulb Temperature,hourly;") - elif variable == "Zone Operative Temperature": - self.idf.add_object("Output:Variable,*,Zone Operative Temperature,hourly; !- Zone Average [C];") - elif variable == "Zone Ideal Loads Zone Total Cooling Rate": - self.idf.add_object("Output:Variable,*,Zone Ideal Loads Zone Total Cooling Rate," - "hourly; !- HVAC Average [W]") - elif variable == "Zone Ideal Loads Zone Total Heating Rate": - self.idf.add_object("Output:Variable,*,Zone Ideal Loads Zone Total Heating Rate," - "hourly; !- HVAC Average [W]") - elif variable == "Surface Outside Face Sunlit Fraction": - self.idf.add_object("Output:Variable,*,Surface Outside Face Sunlit Fraction,hourly; !- Zone Average []") + + # Add output variable objects + if not output_variables: + raise ValueError("Missing output variables") + if "Zone Ideal Loads Zone Total Cooling Energy" in output_variables: + self.idf.add_object("Output:Variable,*,Zone Ideal Loads Zone Total Cooling Energy," + "hourly; !- HVAC Sum [J]") + if "Zone Ideal Loads Zone Total Heating Energy" in output_variables: + self.idf.add_object("Output:Variable,*,Zone Ideal Loads Zone Total Heating Energy," + "hourly; !- HVAC Sum [J]") + if "Site Indoor Air Drybulb Temperature" in output_variables: + self.idf.add_object("Output:Variable,, Site Indoor Air Drybulb Temperature,hourly;") + if "Zone Operative Temperature" in output_variables: + self.idf.add_object("Output:Variable,*,Zone Operative Temperature,hourly; !- Zone Average [C];") + if "Zone Ideal Loads Zone Total Cooling Rate" in output_variables: + self.idf.add_object("Output:Variable,*,Zone Ideal Loads Zone Total Cooling Rate," + "hourly; !- HVAC Average [W]") + if "Zone Ideal Loads Zone Total Heating Rate" in output_variables: + self.idf.add_object("Output:Variable,*,Zone Ideal Loads Zone Total Heating Rate," + "hourly; !- HVAC Average [W]") + if "Surface Outside Face Sunlit Fraction" in output_variables: + self.idf.add_object("Output:Variable,*,Surface Outside Face Sunlit Fraction,hourly; !- Zone Average []") print("Time taken to create IDF: {}".format((time.clock() - start1)/60)) diff --git a/bpeng/simulation/building_hvac_oplus.py b/bpeng/simulation/building_hvac_oplus.py index a9b8437..a91509d 100644 --- a/bpeng/simulation/building_hvac_oplus.py +++ b/bpeng/simulation/building_hvac_oplus.py @@ -3,7 +3,7 @@ Add the IDF objects for modeling a ZoneHVAC:IdealAirLoadsSystem for each zone (e author: Thomas """ - +# pylint: disable=invalid-name # Default IDF objects to modify. Filled with default values or None. zone_thermostat_default = """ZoneControl:Thermostat, diff --git a/bpeng/simulation/design_days.py b/bpeng/simulation/design_days.py index f2b83c4..0856c81 100644 --- a/bpeng/simulation/design_days.py +++ b/bpeng/simulation/design_days.py @@ -4,8 +4,7 @@ Design Days storage for New York author: Thomas """ -import oplus - +# pylint: disable=line-too-long,invalid-name,dangerous-default-value ddaylist = [ """SizingPeriod:DesignDay, NEW_YORK Ann Clg .4% Condns DB=>MWB, !- Name diff --git a/bpeng/simulation/extract_output.py b/bpeng/simulation/extract_output.py index d79aeea..7ee0ac0 100644 --- a/bpeng/simulation/extract_output.py +++ b/bpeng/simulation/extract_output.py @@ -3,6 +3,8 @@ import xml.etree.ElementTree as ET import oplus as op import pandas as pd +# pylint: disable=too-many-locals,invalid-name + # Conversion factors J_to_kWh = 1/3600*1/1000 therms_to_kWh = 29.3001 @@ -87,7 +89,27 @@ def epxml_zcls_to_df(xml_file_path, bin_num, output_details='TotalOnly'): def heat_cool_dist_from_eso(eso_file_path, bin_num, time_step="Hourly"): """ + Extract heating and cooling distribution from EnergyPlus eso output files for specific building + + Args: + + eso_file_path (str) + path to eso file that will be parsed + + bin_num (float or int) + Building Identification Number + + time_step (str) + Time increment of output + Defaults to "Hourly", additional option: "Monthly" + + Returns: + + pandas.DataFrame: heating and cooling distribution based on specified time step + + Raises: + ValueError: If input time_step is missing or mispelled """ out = op.StandardOutputFile(eso_file_path) df_eso = out.df(time_step="Hourly", environment="RunPeriod") @@ -121,7 +143,28 @@ def heat_cool_dist_from_eso(eso_file_path, bin_num, time_step="Hourly"): def hvac_sizing_from_eio(eio_file_path, bin_num, output_type='TotalSizing'): """ + Extract HVAC sizing from EnergyPlus eio output files for specific building + + Args: + + eio_file_path (str) + path to eio file that will be parsed + + bin_num (float or int) + Building Identification Number + + output_type (str) + Specify level of details of output + Defaults to "TotalSizing", which sums all zone loads for the building + Additional option: "All", returns all data for every zones + + Returns: + + pandas.DataFrame: HVAC sizing based on specified time step + + Raises: + ValueError: If input output_type is missing or mispelled """ out_eio = op.eio.EIO(eio_file_path) zone_sizing = out_eio.df(table_ref='Zone Sizing Information') diff --git a/bpeng/simulation/geometry.py b/bpeng/simulation/geometry.py index e232f18..24102de 100644 --- a/bpeng/simulation/geometry.py +++ b/bpeng/simulation/geometry.py @@ -14,6 +14,7 @@ import shapely from geopy.distance import vincenty +# pylint: disable=invalid-name def reverse_list(lst): return [lst[-i] for i in range(1, len(lst) + 1)] @@ -178,6 +179,17 @@ def coord_to_meters(): def fix_dup_id(df, buildid_colname): """ Fix duplicate Building Identification Number (BIN) issue from NYC building footprints shapefile + + Args: + + df (pandas.DataFrame) + + buildid_colname (str) + Building id column name from df DataFrame where duplicates are checked for + + Returns: + + pandas.DataFrame: same df DataFrame with new unique building id number for duplicate building id """ vc_list = df[buildid_colname].value_counts() dupbin_list = vc_list[vc_list > 1] diff --git a/bpeng/simulation/midrise.py b/bpeng/simulation/midrise.py index dd5aa2f..e719e29 100644 --- a/bpeng/simulation/midrise.py +++ b/bpeng/simulation/midrise.py @@ -3,6 +3,7 @@ import numpy as np from .base import BaseSim, NYCShpVal +# pylint: disable=too-many-statements,too-many-branches class MidRiseApart(BaseSim): """ Class for MidRise Apartment buildings based on energy.gov commercial reference buildings, climate zone 4A -- GitLab From cd35b71e518faa1178b2c5176cbdde69846bdf22 Mon Sep 17 00:00:00 2001 From: Michel Date: Wed, 26 Apr 2017 17:32:07 -0400 Subject: [PATCH 14/20] Add conda requirements --- requirements-conda.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 requirements-conda.txt diff --git a/requirements-conda.txt b/requirements-conda.txt new file mode 100644 index 0000000..65cf57a --- /dev/null +++ b/requirements-conda.txt @@ -0,0 +1 @@ +shapely==1.5.17 -- GitLab From 3c4375b2f02386dbb6eb71b5ec3349530af6d0df Mon Sep 17 00:00:00 2001 From: Michel Date: Wed, 26 Apr 2017 17:34:42 -0400 Subject: [PATCH 15/20] Install conda requirements in jenkins --- Jenkinsfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Jenkinsfile b/Jenkinsfile index e466f67..99a2f1b 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -14,6 +14,7 @@ pipeline { sh """ source venv/bin/activate pip install -r requirements-dev.txt + pip install -r requirements-conda.txt """ } } -- GitLab From 5591f8b03065a6128b0fc596415c0658514d3283 Mon Sep 17 00:00:00 2001 From: Michel Date: Wed, 26 Apr 2017 17:52:26 -0400 Subject: [PATCH 16/20] Format design days ddaylist --- bpeng/simulation/design_days.py | 383 +++++++++++++++++--------------- 1 file changed, 198 insertions(+), 185 deletions(-) diff --git a/bpeng/simulation/design_days.py b/bpeng/simulation/design_days.py index 0856c81..2cfd87a 100644 --- a/bpeng/simulation/design_days.py +++ b/bpeng/simulation/design_days.py @@ -6,191 +6,204 @@ author: Thomas # pylint: disable=line-too-long,invalid-name,dangerous-default-value ddaylist = [ - """SizingPeriod:DesignDay, - NEW_YORK Ann Clg .4% Condns DB=>MWB, !- Name - 7, !- Month - 21, !- Day of Month - SummerDesignDay, !- Day Type - 32.1, !- Maximum Dry-Bulb Temperature {C} - 7.4, !- Daily Dry-Bulb Temperature Range {deltaC} - DefaultMultipliers, !- Dry-Bulb Temperature Range Modifier Type - , !- Dry-Bulb Temperature Range Modifier Day Schedule Name - Wetbulb, !- Humidity Condition Type - 23.1, !- Wetbulb or DewPoint at Maximum Dry-Bulb {C} - , !- Humidity Condition Day Schedule Name - , !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir} - , !- Enthalpy at Maximum Dry-Bulb {J/kg} - , !- Daily Wet-Bulb Temperature Range {deltaC} - 100642, !- Barometric Pressure {Pa} - 5.6, !- Wind Speed {m/s} - 230, !- Wind Direction {deg} - No, !- Rain Indicator - No, !- Snow Indicator - No, !- Daylight Saving Time Indicator - ASHRAETau, !- Solar Model Indicator - , !- Beam Solar Day Schedule Name - , !- Diffuse Solar Day Schedule Name - 0.541, !- ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) {dimensionless} - 1.8; !- ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) {dimensionless}""", - """SizingPeriod:DesignDay, - NEW_YORK Ann Clg .4% Condns DP=>MDB, !- Name - 7, !- Month - 21, !- Day of Month - SummerDesignDay, !- Day Type - 27, !- Maximum Dry-Bulb Temperature {C} - 7.4, !- Daily Dry-Bulb Temperature Range {deltaC} - DefaultMultipliers, !- Dry-Bulb Temperature Range Modifier Type - , !- Dry-Bulb Temperature Range Modifier Day Schedule Name - Dewpoint, !- Humidity Condition Type - 23.8, !- Wetbulb or DewPoint at Maximum Dry-Bulb {C} - , !- Humidity Condition Day Schedule Name - , !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir} - , !- Enthalpy at Maximum Dry-Bulb {J/kg} - , !- Daily Wet-Bulb Temperature Range {deltaC} - 100642, !- Barometric Pressure {Pa} - 5.6, !- Wind Speed {m/s} - 230, !- Wind Direction {deg} - No, !- Rain Indicator - No, !- Snow Indicator - No, !- Daylight Saving Time Indicator - ASHRAETau, !- Solar Model Indicator - , !- Beam Solar Day Schedule Name - , !- Diffuse Solar Day Schedule Name - 0.541, !- ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) {dimensionless} - 1.8; !- ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) {dimensionless}""", - """SizingPeriod:DesignDay, - NEW_YORK Ann Clg .4% Condns Enth=>MDB, !- Name - 7, !- Month - 21, !- Day of Month - SummerDesignDay, !- Day Type - 29.1, !- Maximum Dry-Bulb Temperature {C} - 7.4, !- Daily Dry-Bulb Temperature Range {deltaC} - DefaultMultipliers, !- Dry-Bulb Temperature Range Modifier Type - , !- Dry-Bulb Temperature Range Modifier Day Schedule Name - Enthalpy, !- Humidity Condition Type - , !- Wetbulb or DewPoint at Maximum Dry-Bulb {C} - , !- Humidity Condition Day Schedule Name - , !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir} - 75700, !- Enthalpy at Maximum Dry-Bulb {J/kg} - , !- Daily Wet-Bulb Temperature Range {deltaC} - 100642, !- Barometric Pressure {Pa} - 5.6, !- Wind Speed {m/s} - 230, !- Wind Direction {deg} - No, !- Rain Indicator - No, !- Snow Indicator - No, !- Daylight Saving Time Indicator - ASHRAETau, !- Solar Model Indicator - , !- Beam Solar Day Schedule Name - , !- Diffuse Solar Day Schedule Name - 0.541, !- ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) {dimensionless} - 1.8; !- ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) {dimensionless}""", - """SizingPeriod:DesignDay, - NEW_YORK Ann Clg .4% Condns WB=>MDB, !- Name - 7, !- Month - 21, !- Day of Month - SummerDesignDay, !- Day Type - 29.1, !- Maximum Dry-Bulb Temperature {C} - 7.4, !- Daily Dry-Bulb Temperature Range {deltaC} - DefaultMultipliers, !- Dry-Bulb Temperature Range Modifier Type - , !- Dry-Bulb Temperature Range Modifier Day Schedule Name - Wetbulb, !- Humidity Condition Type - 25, !- Wetbulb or DewPoint at Maximum Dry-Bulb {C} - , !- Humidity Condition Day Schedule Name - , !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir} - , !- Enthalpy at Maximum Dry-Bulb {J/kg} - , !- Daily Wet-Bulb Temperature Range {deltaC} - 100642, !- Barometric Pressure {Pa} - 5.6, !- Wind Speed {m/s} - 230, !- Wind Direction {deg} - No, !- Rain Indicator - No, !- Snow Indicator - No, !- Daylight Saving Time Indicator - ASHRAETau, !- Solar Model Indicator - , !- Beam Solar Day Schedule Name - , !- Diffuse Solar Day Schedule Name - 0.541, !- ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) {dimensionless} - 1.8; !- ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) {dimensionless}""", - """SizingPeriod:DesignDay, - NEW_YORK Ann Htg 99.6% Condns DB, !- Name - 1, !- Month - 21, !- Day of Month - WinterDesignDay, !- Day Type - -10.7, !- Maximum Dry-Bulb Temperature {C} - 0, !- Daily Dry-Bulb Temperature Range {deltaC} - DefaultMultipliers, !- Dry-Bulb Temperature Range Modifier Type - , !- Dry-Bulb Temperature Range Modifier Day Schedule Name - Wetbulb, !- Humidity Condition Type - -10.7, !- Wetbulb or DewPoint at Maximum Dry-Bulb {C} - , !- Humidity Condition Day Schedule Name - , !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir} - , !- Enthalpy at Maximum Dry-Bulb {J/kg} - , !- Daily Wet-Bulb Temperature Range {deltaC} - 100642, !- Barometric Pressure {Pa} - 7.5, !- Wind Speed {m/s} - 320, !- Wind Direction {deg} - No, !- Rain Indicator - No, !- Snow Indicator - No, !- Daylight Saving Time Indicator - ASHRAEClearSky, !- Solar Model Indicator - , !- Beam Solar Day Schedule Name - , !- Diffuse Solar Day Schedule Name - , !- ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) {dimensionless} - , !- ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) {dimensionless} - 0; !- Sky Clearness""", - """SizingPeriod:DesignDay, - NEW_YORK Ann Htg Wind 99.6% Condns WS=>MCDB, !- Name - 1, !- Month - 21, !- Day of Month - WinterDesignDay, !- Day Type - -3.2, !- Maximum Dry-Bulb Temperature {C} - 0, !- Daily Dry-Bulb Temperature Range {deltaC} - DefaultMultipliers, !- Dry-Bulb Temperature Range Modifier Type - , !- Dry-Bulb Temperature Range Modifier Day Schedule Name - Wetbulb, !- Humidity Condition Type - -3.2, !- Wetbulb or DewPoint at Maximum Dry-Bulb {C} - , !- Humidity Condition Day Schedule Name - , !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir} - , !- Enthalpy at Maximum Dry-Bulb {J/kg} - , !- Daily Wet-Bulb Temperature Range {deltaC} - 100642, !- Barometric Pressure {Pa} - 14.2, !- Wind Speed {m/s} - 320, !- Wind Direction {deg} - No, !- Rain Indicator - No, !- Snow Indicator - No, !- Daylight Saving Time Indicator - ASHRAEClearSky, !- Solar Model Indicator - , !- Beam Solar Day Schedule Name - , !- Diffuse Solar Day Schedule Name - , !- ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) {dimensionless} - , !- ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) {dimensionless} - 0; !- Sky Clearness""", - """SizingPeriod:DesignDay, - NEW_YORK Ann Hum_n 99.6% Condns DP=>MCDB, !- Name - 1, !- Month - 21, !- Day of Month - WinterDesignDay, !- Day Type - -8.9, !- Maximum Dry-Bulb Temperature {C} - 0, !- Daily Dry-Bulb Temperature Range {deltaC} - DefaultMultipliers, !- Dry-Bulb Temperature Range Modifier Type - , !- Dry-Bulb Temperature Range Modifier Day Schedule Name - Dewpoint, !- Humidity Condition Type - -20.8, !- Wetbulb or DewPoint at Maximum Dry-Bulb {C} - , !- Humidity Condition Day Schedule Name - , !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir} - , !- Enthalpy at Maximum Dry-Bulb {J/kg} - , !- Daily Wet-Bulb Temperature Range {deltaC} - 100642, !- Barometric Pressure {Pa} - 7.5, !- Wind Speed {m/s} - 320, !- Wind Direction {deg} - No, !- Rain Indicator - No, !- Snow Indicator - No, !- Daylight Saving Time Indicator - ASHRAEClearSky, !- Solar Model Indicator - , !- Beam Solar Day Schedule Name - , !- Diffuse Solar Day Schedule Name - , !- ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) {dimensionless} - , !- ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) {dimensionless} - 0; !- Sky Clearness""" + """ + SizingPeriod:DesignDay, + NEW_YORK Ann Clg .4% Condns DB=>MWB, !- Name + 7, !- Month + 21, !- Day of Month + SummerDesignDay, !- Day Type + 32.1, !- Maximum Dry-Bulb Temperature {C} + 7.4, !- Daily Dry-Bulb Temperature Range {deltaC} + DefaultMultipliers, !- Dry-Bulb Temperature Range Modifier Type + , !- Dry-Bulb Temperature Range Modifier Day Schedule Name + Wetbulb, !- Humidity Condition Type + 23.1, !- Wetbulb or DewPoint at Maximum Dry-Bulb {C} + , !- Humidity Condition Day Schedule Name + , !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir} + , !- Enthalpy at Maximum Dry-Bulb {J/kg} + , !- Daily Wet-Bulb Temperature Range {deltaC} + 100642, !- Barometric Pressure {Pa} + 5.6, !- Wind Speed {m/s} + 230, !- Wind Direction {deg} + No, !- Rain Indicator + No, !- Snow Indicator + No, !- Daylight Saving Time Indicator + ASHRAETau, !- Solar Model Indicator + , !- Beam Solar Day Schedule Name + , !- Diffuse Solar Day Schedule Name + 0.541, !- ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) {dimensionless} + 1.8; !- ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) {dimensionless} + """, + """ + SizingPeriod:DesignDay, + NEW_YORK Ann Clg .4% Condns DP=>MDB, !- Name + 7, !- Month + 21, !- Day of Month + SummerDesignDay, !- Day Type + 27, !- Maximum Dry-Bulb Temperature {C} + 7.4, !- Daily Dry-Bulb Temperature Range {deltaC} + DefaultMultipliers, !- Dry-Bulb Temperature Range Modifier Type + , !- Dry-Bulb Temperature Range Modifier Day Schedule Name + Dewpoint, !- Humidity Condition Type + 23.8, !- Wetbulb or DewPoint at Maximum Dry-Bulb {C} + , !- Humidity Condition Day Schedule Name + , !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir} + , !- Enthalpy at Maximum Dry-Bulb {J/kg} + , !- Daily Wet-Bulb Temperature Range {deltaC} + 100642, !- Barometric Pressure {Pa} + 5.6, !- Wind Speed {m/s} + 230, !- Wind Direction {deg} + No, !- Rain Indicator + No, !- Snow Indicator + No, !- Daylight Saving Time Indicator + ASHRAETau, !- Solar Model Indicator + , !- Beam Solar Day Schedule Name + , !- Diffuse Solar Day Schedule Name + 0.541, !- ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) {dimensionless} + 1.8; !- ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) {dimensionless} + """, + """ + SizingPeriod:DesignDay, + NEW_YORK Ann Clg .4% Condns Enth=>MDB, !- Name + 7, !- Month + 21, !- Day of Month + SummerDesignDay, !- Day Type + 29.1, !- Maximum Dry-Bulb Temperature {C} + 7.4, !- Daily Dry-Bulb Temperature Range {deltaC} + DefaultMultipliers, !- Dry-Bulb Temperature Range Modifier Type + , !- Dry-Bulb Temperature Range Modifier Day Schedule Name + Enthalpy, !- Humidity Condition Type + , !- Wetbulb or DewPoint at Maximum Dry-Bulb {C} + , !- Humidity Condition Day Schedule Name + , !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir} + 75700, !- Enthalpy at Maximum Dry-Bulb {J/kg} + , !- Daily Wet-Bulb Temperature Range {deltaC} + 100642, !- Barometric Pressure {Pa} + 5.6, !- Wind Speed {m/s} + 230, !- Wind Direction {deg} + No, !- Rain Indicator + No, !- Snow Indicator + No, !- Daylight Saving Time Indicator + ASHRAETau, !- Solar Model Indicator + , !- Beam Solar Day Schedule Name + , !- Diffuse Solar Day Schedule Name + 0.541, !- ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) {dimensionless} + 1.8; !- ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) {dimensionless} + """, + """ + SizingPeriod:DesignDay, + NEW_YORK Ann Clg .4% Condns WB=>MDB, !- Name + 7, !- Month + 21, !- Day of Month + SummerDesignDay, !- Day Type + 29.1, !- Maximum Dry-Bulb Temperature {C} + 7.4, !- Daily Dry-Bulb Temperature Range {deltaC} + DefaultMultipliers, !- Dry-Bulb Temperature Range Modifier Type + , !- Dry-Bulb Temperature Range Modifier Day Schedule Name + Wetbulb, !- Humidity Condition Type + 25, !- Wetbulb or DewPoint at Maximum Dry-Bulb {C} + , !- Humidity Condition Day Schedule Name + , !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir} + , !- Enthalpy at Maximum Dry-Bulb {J/kg} + , !- Daily Wet-Bulb Temperature Range {deltaC} + 100642, !- Barometric Pressure {Pa} + 5.6, !- Wind Speed {m/s} + 230, !- Wind Direction {deg} + No, !- Rain Indicator + No, !- Snow Indicator + No, !- Daylight Saving Time Indicator + ASHRAETau, !- Solar Model Indicator + , !- Beam Solar Day Schedule Name + , !- Diffuse Solar Day Schedule Name + 0.541, !- ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) {dimensionless} + 1.8; !- ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) {dimensionless} + """, + """ + SizingPeriod:DesignDay, + NEW_YORK Ann Htg 99.6% Condns DB, !- Name + 1, !- Month + 21, !- Day of Month + WinterDesignDay, !- Day Type + -10.7, !- Maximum Dry-Bulb Temperature {C} + 0, !- Daily Dry-Bulb Temperature Range {deltaC} + DefaultMultipliers, !- Dry-Bulb Temperature Range Modifier Type + , !- Dry-Bulb Temperature Range Modifier Day Schedule Name + Wetbulb, !- Humidity Condition Type + -10.7, !- Wetbulb or DewPoint at Maximum Dry-Bulb {C} + , !- Humidity Condition Day Schedule Name + , !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir} + , !- Enthalpy at Maximum Dry-Bulb {J/kg} + , !- Daily Wet-Bulb Temperature Range {deltaC} + 100642, !- Barometric Pressure {Pa} + 7.5, !- Wind Speed {m/s} + 320, !- Wind Direction {deg} + No, !- Rain Indicator + No, !- Snow Indicator + No, !- Daylight Saving Time Indicator + ASHRAEClearSky, !- Solar Model Indicator + , !- Beam Solar Day Schedule Name + , !- Diffuse Solar Day Schedule Name + , !- ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) {dimensionless} + , !- ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) {dimensionless} + 0; !- Sky Clearness + """, + """ + SizingPeriod:DesignDay, + NEW_YORK Ann Htg Wind 99.6% Condns WS=>MCDB, !- Name + 1, !- Month + 21, !- Day of Month + WinterDesignDay, !- Day Type + -3.2, !- Maximum Dry-Bulb Temperature {C} + 0, !- Daily Dry-Bulb Temperature Range {deltaC} + DefaultMultipliers, !- Dry-Bulb Temperature Range Modifier Type + , !- Dry-Bulb Temperature Range Modifier Day Schedule Name + Wetbulb, !- Humidity Condition Type + -3.2, !- Wetbulb or DewPoint at Maximum Dry-Bulb {C} + , !- Humidity Condition Day Schedule Name + , !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir} + , !- Enthalpy at Maximum Dry-Bulb {J/kg} + , !- Daily Wet-Bulb Temperature Range {deltaC} + 100642, !- Barometric Pressure {Pa} + 14.2, !- Wind Speed {m/s} + 320, !- Wind Direction {deg} + No, !- Rain Indicator + No, !- Snow Indicator + No, !- Daylight Saving Time Indicator + ASHRAEClearSky, !- Solar Model Indicator + , !- Beam Solar Day Schedule Name + , !- Diffuse Solar Day Schedule Name + , !- ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) {dimensionless} + , !- ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) {dimensionless} + 0; !- Sky Clearness""", + """ + SizingPeriod:DesignDay, + NEW_YORK Ann Hum_n 99.6% Condns DP=>MCDB, !- Name + 1, !- Month + 21, !- Day of Month + WinterDesignDay, !- Day Type + -8.9, !- Maximum Dry-Bulb Temperature {C} + 0, !- Daily Dry-Bulb Temperature Range {deltaC} + DefaultMultipliers, !- Dry-Bulb Temperature Range Modifier Type + , !- Dry-Bulb Temperature Range Modifier Day Schedule Name + Dewpoint, !- Humidity Condition Type + -20.8, !- Wetbulb or DewPoint at Maximum Dry-Bulb {C} + , !- Humidity Condition Day Schedule Name + , !- Humidity Ratio at Maximum Dry-Bulb {kgWater/kgDryAir} + , !- Enthalpy at Maximum Dry-Bulb {J/kg} + , !- Daily Wet-Bulb Temperature Range {deltaC} + 100642, !- Barometric Pressure {Pa} + 7.5, !- Wind Speed {m/s} + 320, !- Wind Direction {deg} + No, !- Rain Indicator + No, !- Snow Indicator + No, !- Daylight Saving Time Indicator + ASHRAEClearSky, !- Solar Model Indicator + , !- Beam Solar Day Schedule Name + , !- Diffuse Solar Day Schedule Name + , !- ASHRAE Clear Sky Optical Depth for Beam Irradiance (taub) {dimensionless} + , !- ASHRAE Clear Sky Optical Depth for Diffuse Irradiance (taud) {dimensionless} + 0; !- Sky Clearness + """ ] -- GitLab From c9317301e220cd210c7a5d9a230ebf7d8e1b91e0 Mon Sep 17 00:00:00 2001 From: Michel Date: Wed, 26 Apr 2017 18:10:55 -0400 Subject: [PATCH 17/20] Remove units from zoneinfil_post2009_new --- bpeng/simulation/midrise.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bpeng/simulation/midrise.py b/bpeng/simulation/midrise.py index e719e29..9a351ea 100644 --- a/bpeng/simulation/midrise.py +++ b/bpeng/simulation/midrise.py @@ -225,7 +225,7 @@ class MidRiseApart(BaseSim): , !- Design Flow Rate {m3/s} , !- Flow per Zone Floor Area {m3/s-m2} 0.000226568, !- Flow per Exterior Surface Area {m3/s-m2} - , !- Air Changes per Hour {1/hr} + , !- Air Changes per Hour , !- Constant Term Coefficient , !- Temperature Term Coefficient , !- Velocity Term Coefficient -- GitLab From 57eb6e77c7b3c5543a6a944550bb4be8f1807511 Mon Sep 17 00:00:00 2001 From: Michel Date: Wed, 26 Apr 2017 18:14:30 -0400 Subject: [PATCH 18/20] Move enum import above numpy --- bpeng/simulation/base.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bpeng/simulation/base.py b/bpeng/simulation/base.py index b4690d8..eeea943 100644 --- a/bpeng/simulation/base.py +++ b/bpeng/simulation/base.py @@ -7,14 +7,13 @@ import datetime import math import os import time +from enum import Enum import numpy as np import pandas as pd import shapely from oplus import IDF -from enum import Enum - from .building_hvac_oplus import (add_designspec_airdist, add_sch_compact, add_sch_constant, add_sch_typelimits, add_sizing_zone, add_thermostat_dual_setpoints, add_zone_equipmentconnection, add_zone_equipmentlist, add_zone_ideal_airloads, add_zone_thermostat) -- GitLab From 63d987a0f09fcd13b274038b5425381d624b7bde Mon Sep 17 00:00:00 2001 From: Michel Date: Wed, 26 Apr 2017 18:15:58 -0400 Subject: [PATCH 19/20] Add fixme to pylintrc --- .pylintrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pylintrc b/.pylintrc index 69dcd5f..fc54366 100644 --- a/.pylintrc +++ b/.pylintrc @@ -65,7 +65,7 @@ confidence= # --enable=similarities". If you want to run only the classes checker, but have # no Warning level messages displayed, use"--disable=all --enable=classes # --disable=W" -disable=zip-builtin-not-iterating,dict-iter-method,buffer-builtin,raw_input-builtin,print-statement,unpacking-in-except,execfile-builtin,useless-suppression,suppressed-message,map-builtin-not-iterating,using-cmp-argument,dict-view-method,parameter-unpacking,coerce-builtin,input-builtin,unichr-builtin,hex-method,setslice-method,old-division,nonzero-method,cmp-builtin,old-raise-syntax,basestring-builtin,reload-builtin,intern-builtin,getslice-method,cmp-method,long-builtin,apply-builtin,file-builtin,indexing-exception,old-ne-operator,no-absolute-import,round-builtin,metaclass-assignment,range-builtin-not-iterating,standarderror-builtin,delslice-method,backtick,unicode-builtin,xrange-builtin,import-star-module-level,raising-string,long-suffix,oct-method,next-method-called,coerce-method,reduce-builtin,old-octal-literal,filter-builtin-not-iterating,no-member,missing-docstring +disable=zip-builtin-not-iterating,dict-iter-method,buffer-builtin,raw_input-builtin,print-statement,unpacking-in-except,execfile-builtin,useless-suppression,suppressed-message,map-builtin-not-iterating,using-cmp-argument,dict-view-method,parameter-unpacking,coerce-builtin,input-builtin,unichr-builtin,hex-method,setslice-method,old-division,nonzero-method,cmp-builtin,old-raise-syntax,basestring-builtin,reload-builtin,intern-builtin,getslice-method,cmp-method,long-builtin,apply-builtin,file-builtin,indexing-exception,old-ne-operator,no-absolute-import,round-builtin,metaclass-assignment,range-builtin-not-iterating,standarderror-builtin,delslice-method,backtick,unicode-builtin,xrange-builtin,import-star-module-level,raising-string,long-suffix,oct-method,next-method-called,coerce-method,reduce-builtin,old-octal-literal,filter-builtin-not-iterating,no-member,missing-docstring,fixme [REPORTS] -- GitLab From d6fdea90341f274bc1add187415924b4895bbec3 Mon Sep 17 00:00:00 2001 From: Michel Date: Wed, 26 Apr 2017 18:26:08 -0400 Subject: [PATCH 20/20] Delete simulation test file --- tests/simulation/test_midrise_idf.py | 49 ---------------------------- 1 file changed, 49 deletions(-) delete mode 100644 tests/simulation/test_midrise_idf.py diff --git a/tests/simulation/test_midrise_idf.py b/tests/simulation/test_midrise_idf.py deleted file mode 100644 index b513623..0000000 --- a/tests/simulation/test_midrise_idf.py +++ /dev/null @@ -1,49 +0,0 @@ -# import pandas as pd - -# from bpeng.simulation import MidRiseApart - - -# class TestMidRiseApart: -# # FIXME: update test class to match new format -# colnames_list = ['bbl', -# 'bin', -# 'built_code', -# 'cnstrct_yr', -# 'date_lstmo', -# 'doitt_id', -# 'feat_code', -# 'geometry', -# 'groundelev', -# 'heightroof', -# 'lststatype', -# 'name', -# 'num_floors', -# 'shape_area', -# 'shape_len', -# 'sub_code', -# 'time_lstmo'] - -# geometry_poly = 'POLYGON ((-73.94641126946065 40.79089312357564, -73.94652458117535 40.79073642966144, ' \ -# '-73.9466023711673 40.79076892427322, -73.94650177155994 40.79090804098926, ' \ -# '-73.94647668522865 40.790897561923, -73.94646397442928 40.79091513919471, ' \ -# '-73.94641126946065 40.79089312357564))' - -# values_list = [[1016320026, 1051959.0, 'E', 1910.0, '2009-02-14', 744227.0, 2100.0, -# geometry_poly, -# 10.0, 15.0364937268, 'Constructed', "nan", 4.0, 1543.26117443, -# 179.44512646599998, 210000.0, '00:00:00.000']] - -# test_shp = pd.DataFrame(values_list, columns=colnames_list) - -# def setup_class(self): -# self.midrise_idf = MidRiseApart(building_shapefile=self.test_shp) - -# def test_init(self): -# assert self.midrise_idf.build_type == 'MidRiseApart' - -# def test_idf_creation(self): -# self.midrise_idf.idf_creation(building_shapefile=self.test_shp, add_shading_analysis=False, add_people=True, -# add_equipment=True, add_light=True, infiltration_value=1.5) -# bsd = self.midrise_idf.idf("BuildingSurface:Detailed").filter('name', 'Wall 1051959.0 floor1 1').one -# assert bsd['name'] == 'Wall 1051959.0 floor1 1' -# assert bsd['Construction Name']['Name'] == 'Steel Frame Res Ext Wall_stucco_pre1980' -- GitLab