def test_initread(): """Test for IDF.initread() with filename in unicode and as python str.""" # setup idf = IDF() idf.initreadtxt(idfsnippet) idf.saveas("tmp.idf") # test fname as unicode fname = "tmp.idf" assert isinstance(fname, string_types) idf = IDF() idf.initread(fname) assert idf.getobject("BUILDING", "Building") # test fname as str fname = str("tmp.idf") assert isinstance(fname, string_types) idf = IDF() idf.initread(fname) assert idf.getobject("BUILDING", "Building") # test that a nonexistent file raises an IOError fname = "notarealfilename.notreal" idf = IDF() try: idf.initread(fname) assert False # shouldn't reach here except IOError: pass # teardown os.remove("tmp.idf")
def auto_generate_from_template(peak_heating_w, peak_cooling_w, base_LP_idf, base_plant_idf, plant_configuration_json_file, out_dir, final_idf_name, idd_file): expanded_plant_loop_idf = 'expanded.idf' LP_plant_loop_idf = 'plant_loop.idf' temp_base_LP_idf = 'temp_base_LP.idf' # Update the flow rate for the loadprofile:plant objects IDF.setiddname(idd_file) idf = IDF(base_LP_idf) idf = auto_update_LP_flow_rates(idf, peak_heating_w, peak_cooling_w) idf.saveas(temp_base_LP_idf) modify_template_idf(plant_configuration_json_file, base_plant_idf, idd_file=idd_file) expand_template_idf() prepare_LP_plantloop(expanded_plant_loop_idf, LP_plant_loop_idf, idd_file=idd_file) append_files(temp_base_LP_idf, LP_plant_loop_idf, final_idf_name) cleanup(temp_base_LP_idf) cleanup(expanded_plant_loop_idf) cleanup(LP_plant_loop_idf) cleanup('expandedidf.err') cleanup('in.idf') if not os.path.exists(out_dir): os.mkdir(out_dir) shutil.move(final_idf_name, f"{out_dir}{final_idf_name}")
def delete_cmplx_HVAC(originalidf_path,savefolder_path): """ Deletes All HVAC fields It is useful if there is no DHW system modeled in the IDF file :param originalidf_path: Path for the original IDF with a complex HVAC data :return: savefolder_path: Path to use where all converted files will be saved """ # Backup originalidf = IDF(originalidf_path) building=originalidf.idfobjects["Building".upper()][0].Name originalidf.saveas(f"{savefolder_path}\\{building}_BuildME_interim.idf") idf=IDF(f"{savefolder_path}\\{building}_BuildME_interim.idf") # Lets find out all available keys in the IDF file allkeys = idfobjectkeys(idf) # Getting all possible HVAC-related keys by filtering... HVAC_related_list= allkeys[allkeys.index('HVACTEMPLATE:THERMOSTAT'):] HVAC_related_list = HVAC_related_list[:HVAC_related_list.index('MATRIX:TWODIMENSION')] # Deleting all HVAC and DHW objects in our filtered list for HVAC_obj in HVAC_related_list: idf.removeallidfobjects(HVAC_obj) idf.saveas(f"{savefolder_path}\\{building}_BuildME_cleaned.idf") editedidf=idf return editedidf
def write_to_idf(self, edited_schedule, idf_file, new_file): """ method to write schedule to IDF :param edited_schedule: str -> schedule that is edited :param idf_file: original IDF from which base schedule is extracted :param new_file: name of new file to which the schedule is written """ idf_0 = IDF(idfname=idf_file) idf_0.saveas(new_file) with open(new_file, "a") as file: file.write("\n\n") file.write(edited_schedule) idf = IDF(idfname=new_file) # IDF.setiddname(self.idd_file) DualSetpoints = idf.idfobjects["ThermostatSetpoint:DualSetpoint"] if self.schedule_type == "CLGSETP": for DualSetpoint in DualSetpoints: DualSetpoint[ "Cooling_Setpoint_Temperature_Schedule_Name"] = self.schedule_name_edited elif self.schedule_type == "HTGSETP": for DualSetpoint in DualSetpoints: DualSetpoint[ "Heating_Setpoint_Temperature_Schedule_Name"] = self.schedule_name_edited else: print("Enter Valid SETP") idf.saveas(new_file) return None
def test_initread(): """Test for IDF.initread() with filename in unicode and as python str. """ # setup idf = IDF() idf.initreadtxt(idfsnippet) idf.saveas('tmp.idf') # test fname as unicode fname = 'tmp.idf' assert isinstance(fname, string_types) idf = IDF() idf.initread(fname) assert idf.getobject('BUILDING', 'Building') # test fname as str fname = str('tmp.idf') assert isinstance(fname, string_types) idf = IDF() idf.initread(fname) assert idf.getobject('BUILDING', 'Building') # test that a nonexistent file raises an IOError fname = "notarealfilename.notreal" idf = IDF() try: idf.initread(fname) assert False # shouldn't reach here except IOError: pass # teardown os.remove('tmp.idf')
def modify_template_idf(plant_configuration_json_file, base_template_idf='base_plant.idf', modified_template_idf='in.idf', idd_file="C:/EnergyPlusV9-1-0/Energy+.idd"): IDF.setiddname(idd_file) idf = IDF(base_template_idf) with open(plant_configuration_json_file) as json_file: data = json.load(json_file) def add_template_chiller(idf, chiller_name, chiller_type='ElectricCentrifugalChiller', cop=3.5, condenser_type='WaterCooled'): idf.newidfobject("HVACTemplate:Plant:Chiller") idf_new_template_chiller = idf.idfobjects[ 'HVACTemplate:Plant:Chiller'][-1] idf_new_template_chiller.Name = chiller_name idf_new_template_chiller.Chiller_Type = chiller_type idf_new_template_chiller.Nominal_COP = cop idf_new_template_chiller.Condenser_Type = condenser_type idf_new_template_chiller.Priority = 1 idf_new_template_chiller.Sizing_Factor = '' idf_new_template_chiller.Minimum_Part_Load_Ratio = '' idf_new_template_chiller.Maximum_Part_Load_Ratio = '' idf_new_template_chiller.Optimum_Part_Load_Ratio = '' idf_new_template_chiller.Minimum_Unloading_Ratio = '' idf_new_template_chiller.Leaving_Chilled_Water_Lower_Temperature_Limit = '' return idf def add_template_boiler(idf, boiler_name, efficiency=0.8, fuel_type="NaturalGas"): idf.newidfobject("HVACTemplate:Plant:Boiler") idf_new_template_boiler = idf.idfobjects['HVACTemplate:Plant:Boiler'][ -1] idf_new_template_boiler.Name = boiler_name idf_new_template_boiler.Efficiency = efficiency idf_new_template_boiler.Fuel_Type = fuel_type return idf for count, chiller in enumerate(data['chillers']): idf = add_template_chiller(idf, f"Chiller No. {count+1}", chiller['type'], chiller['COP'], chiller['condenser']) for count, boiler in enumerate(data['boilers']): idf = add_template_boiler(idf, f"Boiler No. {count+1}", boiler['efficiency'], fuel_type=boiler['fuel']) print('---> Adding template chiller and boiler done.') idf.saveas(modified_template_idf)
def batch(): t_id = [] city_id = [] length = [] width = [] height = [] window = [] orient = [] i = 1 for fname1 in fname: idf1 = IDF('baseline/' + fname1) for orientation1 in orientation: for length1 in lengths: for width1 in widths: for height1 in heights: for fenes in fenestration: idf1.idfobjects["ZONE"][ 0].Direction_of_Relative_North = orientation1 idf1 = surfaces(idf1, x=length1, y=width1, z=height1) idf1 = windows(idf1, p=fenes) city1 = re.search('(.*).idf', fname1).group(1) t_id.append(i) city_id.append(city1) length.append(length1) width.append(width1) height.append(height1) window.append(fenes) orient.append(orientation1) idf1.saveas('idf_files/' + city1 + str(i) + '.idf') print(str(i) + "/" + str(total)) i += 1 data_raw = { 'id': t_id, 'city': city_id, 'length': length, 'width': width, 'height': height, 'orientation': orient, 'window_ratio': window } df = pd.DataFrame(data_raw) df.to_csv("model_inputs.csv", index=False)
def test_save_as(self): """Test saveas with a changed filename. IDF.saveas(fname) changes the filename. The next save should save with new name. Fails if the filename isn't changed on the file with the new name. """ idf = IDF(self.startfile) idf.saveas(self.saveasfile) # sets the new filename setversion(idf, '7.4') idf.save() # should also save with the new filename idf2 = IDF(self.saveasfile) result = getversion(idf2) expected = '7.4' assert result == expected
def test_save_as(self): """Test saveas with a changed filename. IDF.saveas(fname) changes the filename. The next save should save with new name. Fails if the filename isn't changed on the file with the new name. """ idf = IDF(self.startfile) idf.saveas(self.saveasfile) # sets the new filename setversion(idf, "7.4") idf.save() # should also save with the new filename idf2 = IDF(self.saveasfile) result = getversion(idf2) expected = "7.4" assert result == expected
def modify_idf(design, designs, idf_path): # Load idf file idf1 = IDF('./Models/ss1_idfs/ss1_{:02d}.idf'.format(design)) # Setup fields to be changed building = 'Building' building = idf1.idfobjects[building.upper()][0] # Set object information building.Name = 'Building Design {:02d}/{:02d}'.format(design, designs) building.North_Axis = '0' print('IDF file setup for {} completed'.format(building.Name)) idf_path = './Models/ss1_idfs' idf1.saveas('{}/ss1_{:02d}.idf'.format(idf_path, design)) idf_file = '{}/ss1_{:02d}.idf'.format(idf_path, design) return idf_file
def test_saveas(): """Test the IDF.saveas() function.""" file_text = "Material,TestMaterial, !- Name" idf = IDF(StringIO(file_text)) idf.idfname = "test.idf" try: idf.saveas() # this should raise an error as no filename is passed assert False except TypeError: pass file_handle = StringIO() idf.saveas(file_handle) # save with a filehandle expected = "TestMaterial" file_handle.seek(0) result = file_handle.read() assert expected in result # test the idfname attribute has been changed assert idf.idfname != "test.idf"
def test_saveas(): """Test the IDF.saveas() function. """ file_text = "Material,TestMaterial, !- Name" idf = IDF(StringIO(file_text)) idf.idfname = 'test.idf' try: idf.saveas() # this should raise an error as no filename is passed assert False except TypeError: pass file_handle = StringIO() idf.saveas(file_handle) # save with a filehandle expected = "TestMaterial" file_handle.seek(0) result = file_handle.read() assert expected in result # test the idfname attribute has been changed assert idf.idfname != 'test.idf'
def createidfinafolder(): """make a temp dir and save an idf in it :Teardown: remove the temp dir and it'a contents""" # make a temp dir tdirname = "./atempdir1" abspath = os.path.abspath(tdirname) os.mkdir(tdirname) # make blank file idftxt = "" # empty string fhandle = StringIO(idftxt) idf = IDF(fhandle) # put in some objects - building and version building = idf.newidfobject("building") building.Name = "Taj" idf.newidfobject("version") # save it in subdir1 fname = f"{tdirname}/a.idf" idf.saveas(fname) yield idf # Teardown # remove the temp dir shutil.rmtree(abspath)
def datacomp(yc_keys, xc_keys, tc_keys): iddfile = "./Energy+9.1.idd" IDF.setiddname(iddfile) yc_df = pd.DataFrame(columns=yc_keys) xc_df = pd.DataFrame(columns=xc_keys) tc_df = pd.DataFrame(columns=tc_keys) for n in range(len(LHS_result)): idfname = "./RefBldgLargeOfficeNew2004_Chicago.idf" idf = IDF(idfname) # change the output variable and meter # output_frequency='Daily' output_frequency = 'Monthly' variable = [] for i in range(len(xc_keys)): variable1 = idf.newidfobject("Output:Variable".upper()) variable1.Key_Value = '*' variable1.Variable_Name = xc_keys[i] variable1.Reporting_Frequency = output_frequency variable.append(variable1) idf.idfobjects['Output:Variable'.upper()] = variable meter = [] for i in range(len(yc_keys)): meter1 = idf.newidfobject("Output:Meter".upper()) meter1.Key_Name = yc_keys[i] meter1.Reporting_Frequency = output_frequency meter.append(meter1) idf.idfobjects['Output:Meter'.upper()] = meter # change the runperiod and other idf objects for i in range(len(idf.idfobjects['LIGHTS'])): idf.idfobjects['LIGHTS'][i].Watts_per_Zone_Floor_Area = LHS_result[ n][0] for i in range(len(idf.idfobjects['ELECTRICEQUIPMENT'])): idf.idfobjects['ELECTRICEQUIPMENT'][ i].Watts_per_Zone_Floor_Area = LHS_result[n][1] for i in range(len(idf.idfobjects['FAN:VARIABLEVOLUME'])): # idf.idfobjects['FAN:VARIABLEVOLUME'][i].Pressure_Rise=LHS_result[n][2] idf.idfobjects['FAN:VARIABLEVOLUME'][ i].Fan_Total_Efficiency = LHS_result[n][2] for i in range(len(idf.idfobjects['ZONEINFILTRATION:DESIGNFLOWRATE'])): idf.idfobjects['ZONEINFILTRATION:DESIGNFLOWRATE'][ i].Flow_per_Exterior_Surface_Area = LHS_result[n][3] for i in range(len( idf.idfobjects['CHILLER:ELECTRIC:REFORMULATEDEIR'])): idf.idfobjects['CHILLER:ELECTRIC:REFORMULATEDEIR'][ i].Reference_COP = LHS_result[n][4] for i in range(len(idf.idfobjects['BOILER:HOTWATER'])): idf.idfobjects['BOILER:HOTWATER'][ i].Nominal_Thermal_Efficiency = LHS_result[n][5] # for i in range(len(idf.idfobjects['SCHEDULE:COMPACT'])): # if 'Building_Cooling_Sp_Schedule' in idf.idfobjects['SCHEDULE:COMPACT'][i].Name: # idf.idfobjects['SCHEDULE:COMPACT'][i].Field_4=LHS_result[n][4] idf.idfobjects['RUNPERIOD'][0].Begin_Month = 1 idf.idfobjects['RUNPERIOD'][0].Begin_Day_of_Month = 1 idf.idfobjects['RUNPERIOD'][0].End_Month = 12 idf.idfobjects['RUNPERIOD'][0].End_Day_of_Month = 31 idf.saveas('C:/Users/songc/Desktop/work file/Updated_Model.idf') idfname1 = 'C:/Users/songc/Desktop/work file/Updated_Model.idf' # This IDF file is updated at each iteration. epwfile = './SPtMasterTable_52384_2011_amy.epw' subprocess.call([ 'C:/EnergyPlusV9-1-0/energyplus.exe', '-d', "C:/Users/songc/Desktop/work file/result_folder", '-w', epwfile, idfname1 ]) eso_file = './result_folder/eplusout.eso' [ycoutput, xcoutput] = comp_data_reader(eso_file, yc_keys, xc_keys) yc_df = yc_df.append(pd.DataFrame(ycoutput, index=yc_keys).T) xc_df = xc_df.append(pd.DataFrame(xcoutput, index=xc_keys).T) tc_df = tc_df.append( pd.DataFrame(np.reshape( list(LHS_result[n]) * len(ycoutput[0]), (len(ycoutput[0]), len(tc_keys))), columns=tc_keys)) df = pd.concat([yc_df, xc_df, tc_df], axis=1) df.to_csv('DATACOMP_Multi.csv', index=False) df_single = pd.concat([yc_df.iloc[:, 0], xc_df, tc_df], axis=1) df_single.to_csv('DATACOMP_Single.csv', index=False)
def create_IdealLoads_objects(originalidf_path,savefolder_path): """ Function to get inputs from the interim file and using them to create new IdealLoads objects :param originalidf_path: Path for the original IDF with a complex HVAC data :param savefolder_path: Path to use where all converted files will be saved :return: """ # Backup originalidf = IDF(originalidf_path) building=originalidf.idfobjects["Building".upper()][0].Name interimidf = IDF(f"{savefolder_path}\\{building}_BuildME_interim.idf") editedidf= IDF(f"{savefolder_path}\\{building}_BuildME_cleaned.idf") zone_names = editedidf.idfobjects["Zone".upper()] for zone in zone_names: # Generic Parameter Definition newzone = editedidf.newidfobject("HVACTemplate:Zone:IdealLoadsAirSystem") newthermos = editedidf.newidfobject("HVACTemplate:Thermostat") newzone.Zone_Name = zone.Name newthermos.Name = "dual_thermostat_" + zone.Name newzone.Template_Thermostat_Name = newthermos.Name newzone.System_Availability_Schedule_Name = "ALWAYS_ON" newzone.Heating_Availability_Schedule_Name = "ALWAYS_ON" newzone.Cooling_Availability_Schedule_Name = "ALWAYS_ON" newzone.Maximum_Heating_Air_Flow_Rate = "autosize" newzone.Maximum_Sensible_Heating_Capacity = "autosize" newzone.Maximum_Total_Cooling_Capacity = "autosize" newzone.Maximum_Cooling_Air_Flow_Rate = "autosize" newzone.Humidification_Setpoint = "65" newzone.Dehumidification_Setpoint = "" newzone.Heating_Limit = "LimitFlowRateAndCapacity" newzone.Cooling_Limit = "LimitFlowRateAndCapacity" # Customization Part: Getting the approximate values from the complex HVAC version of the IDF for items in interimidf.idfobjects["DesignSpecification:OutdoorAir".upper()]: if newzone.Zone_Name in items.Name: newzone.Outdoor_Air_Flow_Rate_per_Zone_Floor_Area = items.Outdoor_Air_Flow_per_Zone_Floor_Area newzone.Outdoor_Air_Method = items.Outdoor_Air_Method for items in interimidf.idfobjects["Sizing:Zone".upper()]: if newzone.Zone_Name == items.Zone_or_ZoneList_Name: newzone.Minimum_Cooling_Supply_Air_Humidity_Ratio = items.Zone_Cooling_Design_Supply_Air_Humidity_Ratio newzone.Maximum_Heating_Supply_Air_Humidity_Ratio = items.Zone_Heating_Design_Supply_Air_Humidity_Ratio newzone.Minimum_Cooling_Supply_Air_Temperature = items.Zone_Cooling_Design_Supply_Air_Temperature newzone.Maximum_Heating_Supply_Air_Temperature = items.Zone_Heating_Design_Supply_Air_Temperature for items in interimidf.idfobjects["Controller:OutdoorAir".upper()]: newzone.Outdoor_Air_Economizer_Type = items.Economizer_Control_Type for items in interimidf.idfobjects["AirLoopHVAC:UnitarySystem".upper()]: newzone.Dehumidification_Control_Type = items.Dehumidification_Control_Type # Warning: The following code creates missing fields if the schedule names do not correspond the zone name for items in interimidf.idfobjects["ThermostatSetpoint:DualSetpoint".upper()]: if newzone.Zone_Name in items.Name: newthermos.Heating_Setpoint_Schedule_Name = items.Heating_Setpoint_Temperature_Schedule_Name newthermos.Cooling_Setpoint_Schedule_Name = items.Cooling_Setpoint_Temperature_Schedule_Name building = str(editedidf.idfobjects["Building".upper()][0].Name) editedidf.saveas(f"IdealLoads_{building}_converted.idf") os.remove(f"{savefolder_path}\\{building}_BuildME_interim.idf") os.remove(f"{savefolder_path}\\{building}_BuildME_cleaned.idf") return print("The conversion process is completed, the new IDF with Ideal Loads is saved")
# <markdowncell> # This is easy: # <codecell> idf1.save() # <markdowncell> # If you'd like to do a "Save as..." use this: # <codecell> idf1.saveas('something.idf') # <headingcell level=2> # Working with E+ objects # <markdowncell> # Let us open a small idf file that has only "CONSTRUCTION" and "MATERIAL" objects in it. You can go into "../idffiles/V_7_2/constructions.idf" and take a look at the file. We are not printing it here because it is too big. # # So let us open it using the idfreader - # <codecell> from eppy import modeleditor from eppy.modeleditor import IDF
iddfile = "../../eppy/resources/iddfiles/Energy+V8_1_0.idd" fname1 = "../../eppy/resources/idffiles/V8_1_0/Boiler.idf" # In[2]: IDF.setiddname(iddfile) idf1 = IDF(fname1) # In[3]: idf1 = IDF(fname1) # In[4]: idf1.saveas("bl_original.idf") # In[5]: keys = list(idf1.idfobjects.keys()) # In[6]: # rename object name with a colon and any field that refers to that name from eppy.bunch_subclass import BadEPFieldError renamednames = [] for key in keys: for idfobject in idf1.idfobjects[key]: try: name = idfobject.Name
def main(): idf_name_in = 'Baseline.idf' idf_name_out_1 = 'Calibrating.idf' idf_name_out_2 = 'Calibrating_HM_Occ.idf' idf_name_out_3 = 'Calibrating_v0.3.idf' epw_name = 'in.epw' dir_name = os.path.dirname(os.path.realpath(__file__)) idd_file = "C:/EnergyPlusV8-9-0/Energy+.idd" IDF.setiddname(idd_file) idf_path = dir_name + '/' + idf_name_in epw_path = dir_name + '/' + epw_name out = dir_name + '/out_' + idf_name_in.split('.idf')[0] idf = IDF(idf_path, epw_path) # idf.saveas('Baseline_v0.0.idf') # idf.saveas("tweaked_CBES_model_v0.0.idf") v_materials = idf.idfobjects['MATERIAL'] v_window_materials = idf.idfobjects['WINDOWMATERIAL:SIMPLEGLAZINGSYSTEM'] v_constructions = idf.idfobjects['CONSTRUCTION'] v_lights = idf.idfobjects['LIGHTS'] v_equipment = idf.idfobjects['ELECTRICEQUIPMENT'] v_people = idf.idfobjects['PEOPLE'] v_boilers = idf.idfobjects['BOILER:HOTWATER'] v_waterHeaters = idf.idfobjects['WATERHEATER:MIXED'] v_chillers = idf.idfobjects['COIL:COOLING:DX:TWOSPEED'] v_infiltrations = idf.idfobjects['ZONEINFILTRATION:DESIGNFLOWRATE'] v_DS_OA = idf.idfobjects['DESIGNSPECIFICATION:OUTDOORAIR'] # print([construction.Name for construction in v_constructions]) # Calibrating settings t_ext_wall_thickness = 0.8 t_ext_wall_conductivity = 1.5 t_ext_floor_thickness = 1 t_ext_floor_conductivity = 1 t_window_U = 1.2 t_window_SHGC = 0.8 t_LPD = 1 t_EPD = 1 t_occ_density = 1.5 t_boiler_eff = 0.9 t_waterHeater_eff = 0.9 t_chiller_eff = 0.9 t_infiltration = 2.5 t_OA_per_person = 1.4 ############################## Tweak the model ################################# for construction in v_constructions: # 1. Change the exterior wall construction # Change exterior wall construction if ('ext wall' in construction.Name): # print(construction) # Find and change the material of the outside layer material_1st_layer = construction.get_referenced_object( 'Outside_Layer') material_2nd_layer = construction.get_referenced_object('Layer_2') material_3rd_layer = construction.get_referenced_object('Layer_3') material_4th_layer = construction.get_referenced_object('Layer_4') material_1st_layer = modify_object_property( material_1st_layer, 'Thickness', times=t_ext_wall_thickness) material_2nd_layer = modify_object_property( material_2nd_layer, 'Thickness', times=t_ext_wall_thickness) material_3rd_layer = modify_object_property( material_3rd_layer, 'Thickness', times=t_ext_wall_thickness) material_4th_layer = modify_object_property( material_4th_layer, 'Thickness', times=t_ext_wall_thickness) material_1st_layer = modify_object_property( material_1st_layer, 'Conductivity', times=t_ext_wall_conductivity) material_2nd_layer = modify_object_property( material_2nd_layer, 'Conductivity', times=t_ext_wall_conductivity) material_3rd_layer = modify_object_property( material_3rd_layer, 'Conductivity', times=t_ext_wall_conductivity) material_4th_layer = modify_object_property( material_4th_layer, 'Conductivity', times=t_ext_wall_conductivity) # Change interior wall construction if ('int wall' in construction.Name): # print(construction) material_1st_layer = construction.get_referenced_object( 'Outside_Layer') material_2nd_layer = construction.get_referenced_object('Layer_2') # print(material_1st_layer) # print(material_2nd_layer) continue # print(construction) # Change exterior floor construction if ('ext floor' in construction.Name): # print(construction) material_1st_layer = construction.get_referenced_object( 'Outside_Layer') material_2nd_layer = construction.get_referenced_object('Layer_2') material_1st_layer = modify_object_property( material_1st_layer, 'Thickness', times=t_ext_floor_thickness) material_2nd_layer = modify_object_property( material_2nd_layer, 'Thickness', times=t_ext_floor_thickness) material_1st_layer = modify_object_property( material_1st_layer, 'Conductivity', times=t_ext_floor_conductivity) material_2nd_layer = modify_object_property( material_2nd_layer, 'Conductivity', times=t_ext_floor_conductivity) continue # 2. Change the window properties for construction in v_constructions: if ('glazing' in construction.Name): material_1st_layer = construction.get_referenced_object( 'Outside_Layer') material_1st_layer = modify_object_property(material_1st_layer, 'UFactor', times=t_window_U) material_1st_layer = modify_object_property( material_1st_layer, 'Solar_Heat_Gain_Coefficient', times=t_window_SHGC) # idf.saveas(idf_name_out_2) # 3. Change the lighting power density for light in v_lights: light = modify_object_property(light, 'Watts_per_Zone_Floor_Area', times=t_LPD) continue # 4. Change the interior equipment power density for equipment in v_equipment: equipment = modify_object_property(equipment, 'Watts_per_Zone_Floor_Area', times=t_EPD) continue # idf.saveas(idf_name_out_3) # 5. Change the occupancy settings for people in v_people: people = modify_object_property(people, 'People_per_Zone_Floor_Area', times=t_occ_density) continue # 6. Change HVAC equipment for boiler in v_boilers: boiler = modify_object_property(boiler, 'Nominal_Thermal_Efficiency', times=t_boiler_eff) continue for waterHeater in v_waterHeaters: waterHeater = modify_object_property(waterHeater, 'Heater_Thermal_Efficiency', times=t_waterHeater_eff) continue for chiller in v_chillers: chiller = modify_object_property(chiller, 'High_Speed_Gross_Rated_Cooling_COP', times=t_chiller_eff) continue # Change infiltration settings for infiltration in v_infiltrations: infiltration = modify_object_property(infiltration, 'Air_Changes_per_Hour', times=t_infiltration) continue # Change outdoor air design specification for ds_OA in v_DS_OA: ds_OA = modify_object_property(ds_OA, 'Outdoor_Air_Flow_per_Person', times=t_OA_per_person) idf.saveas(idf_name_out_1)
def convert_idf_to_BuildME(idf_path, save_folder_path, replace_string="-en-std-replaceme", replace_string_value="-non-standard", base=False): """ This function creates an individual edited IDF file that is compatible with BuildME framework Requirements for a clear run: 1)Window-Skylight Difference should be addressed in construction name (e.g. name contains "sky") Run Order: -Adds replaceme fields, -Renames Materials, -Renames Constructions, -Defines non-standard U values; if replace_string_value is set accordingly. :param idf_path: path for idf file to be converted, standard file should be used forthe non-standard IDF creation :param save_folder_path: New location folder path, where the new IDF will be saved :param replace_string: Replaceme content (i.e., -en-std-replaceme-res-replacemem-chrt-replaceme), should start with "-" :param replace_string_value: Replacer string corresponding to the replace string (i.e., -standard-RES0-1920), should start with "-" :param base: Boolean value to declare whether the IDF file corresponding to a base IDF :return: A compatible file with BuildME for an IDF with specific features """ idf1 = IDF(idf_path) print( "Conversion is initialized, construction and surface objects are being converted..." ) # CONVERTING CONSTRUCTION NAMES AND INSERTING REPLACEME STRINGS: # It inserts a replaceme string to the building surface object's construction field, adds a new identical construction to the construction object # and renames the construction name corresponding to the replaceme string for items in idf1.idfobjects["BuildingSurface:Detailed".upper()]: for obj in idf1.idfobjects["Construction".upper()]: if obj.Name == items.Construction_Name: if items.Surface_Type == "Roof": items.Construction_Name = f"ext-roof{replace_string}" newcons = idf1.copyidfobject(obj) newcons.Name = f"ext-roof{replace_string_value}" if items.Surface_Type == "Ceiling": if "int" or "ceiling" in items.Construction_Name: items.Construction_Name = f"int-ceiling{replace_string}" newcons = idf1.copyidfobject(obj) newcons.Name = f"int-ceiling{replace_string_value}" if items.Surface_Type == "Floor": if items.Outside_Boundary_Condition == "Surface": items.Construction_Name = f"int-floor{replace_string}" newcons = idf1.copyidfobject(obj) newcons.Name = f"int-floor{replace_string_value}" if items.Outside_Boundary_Condition == "Adiabatic" or items.Outside_Boundary_Condition == "Ground" or items.Outside_Boundary_Condition == "Outdoors" or items.Outside_Boundary_Condition == "GroundSlabPreprocessorAverage": items.Construction_Name = f"ext-floor{replace_string}" newcons = idf1.copyidfobject(obj) newcons.Name = f"ext-floor{replace_string_value}" if items.Surface_Type == "Wall": if "int" in items.Construction_Name: items.Construction_Name = f"int-wall{replace_string}" newcons = idf1.copyidfobject(obj) newcons.Name = f"int-wall{replace_string_value}" else: items.Construction_Name = f"ext-wall{replace_string}" newcons = idf1.copyidfobject(obj) newcons.Name = f"ext-wall{replace_string_value}" if 'CONSTRUCTION:FFACTORGROUNDFLOOR' in [x for x in idf1.idfobjects]: for floor in idf1.idfobjects[ "Construction:FfactorGroundFloor".upper()]: if floor.Name == items.Construction_Name: if items.Surface_Type == "Floor": if items.Outside_Boundary_Condition == "GroundFCfactorMethod": items.Construction_Name = f"{items.Construction_Name}{replace_string}" newcons = idf1.copyidfobject(floor) newcons.Name = f"{floor.Name}{replace_string_value}" if 'CONSTRUCTION:CFACTORUNDERGROUNDWALL' in [ x for x in idf1.idfobjects ]: for wall in idf1.idfobjects[ "Construction:CfactorUndergroundWall".upper()]: if wall.Name == items.Construction_Name: if items.Surface_Type == "Wall": if items.Outside_Boundary_Condition == "GroundFCfactorMethod" or items.Outside_Boundary_Condition == "Adiabatic": items.Construction_Name = f"{items.Construction_Name}{replace_string}" newcons = idf1.copyidfobject(wall) newcons.Name = f"{wall.Name}{replace_string_value}" if 'WINDOW' in [x for x in idf1.idfobjects]: for fenest in idf1.idfobjects["Window".upper()]: fenest.Construction_Name = f"ext-window{replace_string}" if 'DOOR' in [x for x in idf1.idfobjects]: for fenest in idf1.idfobjects["Door".upper()]: fenest.Construction_Name = f"ext-door{replace_string}" if 'FENESTRATIONSURFACE:DETAILED' in [x for x in idf1.idfobjects]: for fenest in idf1.idfobjects["FenestrationSurface:Detailed".upper()]: for obj in idf1.idfobjects["Construction".upper()]: if fenest.Construction_Name == obj.Name: if fenest.Surface_Type == "Window": # there might be skylights: if "sky" in fenest.Construction_Name: fenest.Construction_Name = f"ext-skywindow{replace_string}" newcons = idf1.copyidfobject(obj) newcons.Name = f"ext-skywindow{replace_string_value}" else: fenest.Construction_Name = f"ext-window{replace_string}" newcons = idf1.copyidfobject(obj) newcons.Name = f"ext-window{replace_string_value}" if fenest.Surface_Type == "GlassDoor": fenest.Construction_Name = f"ext-window{replace_string}" newcons = idf1.copyidfobject(obj) newcons.Name = f"ext-window{replace_string_value}" if fenest.Surface_Type == "Door": fenest.Construction_Name = f"ext-door{replace_string}" newcons = idf1.copyidfobject(obj) newcons.Name = f"ext-door{replace_string_value}" # Deleting duplicated construction names unique = reduce(lambda l, x: l.append(x) or l if x not in l else l, idf1.idfobjects["Construction".upper()], []) idf1.removeallidfobjects("CONSTRUCTION") for newcons in unique: idf1.copyidfobject(newcons) if 'CONSTRUCTION:FFACTORGROUNDFLOOR' in [x for x in idf1.idfobjects]: unique = reduce( lambda l, x: l.append(x) or l if x not in l else l, idf1.idfobjects["Construction:FfactorGroundFloor".upper()], []) idf1.removeallidfobjects("CONSTRUCTION:FFACTORGROUNDFLOOR") for newcons in unique: idf1.copyidfobject(newcons) if 'CONSTRUCTION:CFACTORUNDERGROUNDWALL' in [x for x in idf1.idfobjects]: unique = reduce( lambda l, x: l.append(x) or l if x not in l else l, idf1.idfobjects["Construction:CfactorUndergroundWall".upper()], []) idf1.removeallidfobjects("CONSTRUCTION:CFACTORUNDERGROUNDWALL") for newcons in unique: idf1.copyidfobject(newcons) print("Material objects are being converted...") # CONVERTING MATERIALS # For the -non-standard version, values are replaced with %30 worse performing numbers based on the standard/base version. if "-non-standard" in replace_string_value: for items in idf1.idfobjects["Material".upper()]: items.Conductivity = float(items.Conductivity) * 1.3 items.Name = f"{items.Name}{replace_string_value}" for items in idf1.idfobjects["Material:NoMass".upper()]: items.Thermal_Resistance = float(items.Thermal_Resistance) * 0.7 items.Name = f"{items.Name}{replace_string_value}" for items in idf1.idfobjects[ "WindowMaterial:SimpleGlazingSystem".upper()]: items.UFactor = float(items.UFactor) * 1.3 items.Name = f"{items.Name}{replace_string_value}" if 'CONSTRUCTION:FFACTORGROUNDFLOOR' in [x for x in idf1.idfobjects]: for items in idf1.idfobjects[ "Construction:FfactorGroundFloor".upper()]: items.FFactor = float(items.FFactor) * 0.7 if 'CONSTRUCTION:CFACTORUNDERGROUNDWALL' in [ x for x in idf1.idfobjects ]: for items in idf1.idfobjects[ "Construction:CfactorUndergroundWall".upper()]: items.CFactor = float(items.CFactor) * 1.3 # Material names are changed as they represent different values across standards, some identifiers are added based on replacer_string. else: for items in idf1.idfobjects["Material".upper()]: items.Name = f"{items.Name}{replace_string_value}" for items in idf1.idfobjects["Material:NoMass".upper()]: items.Name = f"{items.Name}{replace_string_value}" for items in idf1.idfobjects[ "WindowMaterial:SimpleGlazingSystem".upper()]: items.Name = f"{items.Name}{replace_string_value}" # Construction material layer names are matched with above material changes for items in idf1.idfobjects["Construction".upper()]: for fields in items.fieldnames: if fields == "key": continue if fields == "Name": continue else: if items[fields] == "": continue else: items[fields] = items[fields] + f"{replace_string_value}" # SAVING THE IDF FILE building = str(idf1.idfobjects["Building".upper()][0].Name) if base == True: idf1.idfobjects["Building".upper( )][0].Name = f"BASE{building}{replace_string_value}" idf1.saveas( f"{save_folder_path}/BASE{building}{replace_string_value}-converted.idf" ) else: idf1.idfobjects[ "Building".upper()][0].Name = f"{building}{replace_string_value}" idf1.saveas( f"{save_folder_path}/{building}{replace_string_value}-converted.idf" ) print( f'{idf1.idfobjects["Building".upper()][0].Name} IDF file is converted and saved...' ) return idf1
def main(): idf_name_in = 'tweaked_CBES_model_v0.0.idf' idf_name_out_1 = 'tweaked_CBES_model_v0.1.idf' idf_name_out_2 = 'tweaked_CBES_model_v0.2.idf' idf_name_out_3 = 'tweaked_CBES_model_v0.3.idf' epw_name = 'USA_PA_Pittsburgh.Intl.AP.725200_TMY3.epw' dir_name = os.path.dirname(os.path.realpath(__file__)) idd_file = "C:/EnergyPlusV8-9-0/Energy+.idd" IDF.setiddname(idd_file) idf_path = dir_name + '/' + idf_name_in epw_path = dir_name + '/' + epw_name out = dir_name + '/out_' + idf_name_in.split('.idf')[0] idf = IDF(idf_path, epw_path) # idf.saveas("tweaked_CBES_model_v0.0.idf") v_materials = idf.idfobjects['MATERIAL'] v_window_materials = idf.idfobjects['WINDOWMATERIAL:SIMPLEGLAZINGSYSTEM'] v_constructions = idf.idfobjects['CONSTRUCTION'] v_lights = idf.idfobjects['LIGHTS'] # print([construction.Name for construction in v_constructions]) ############################## Tweak the model ################################# for construction in v_constructions: # 1. Change the exterior wall construction # Change exterior wall construction if ('ext wall' in construction.Name): # print(construction) # Find and change the material of the outside layer material_1st_layer = construction.get_referenced_object( 'Outside_Layer') material_2nd_layer = construction.get_referenced_object('Layer_2') material_3rd_layer = construction.get_referenced_object('Layer_3') material_4th_layer = construction.get_referenced_object('Layer_4') material_1st_layer = modify_material_property(material_1st_layer, 'Thickness', times=2) material_2nd_layer = modify_material_property(material_2nd_layer, 'Thickness', times=2) material_3rd_layer = modify_material_property(material_3rd_layer, 'Thickness', times=2) material_4th_layer = modify_material_property(material_4th_layer, 'Thickness', times=2) material_1st_layer = modify_material_property(material_1st_layer, 'Conductivity', times=0.5) material_2nd_layer = modify_material_property(material_2nd_layer, 'Conductivity', times=0.5) material_3rd_layer = modify_material_property(material_3rd_layer, 'Conductivity', times=0.5) material_4th_layer = modify_material_property(material_4th_layer, 'Conductivity', times=0.5) # Change interior wall construction if ('int wall' in construction.Name): # print(construction) material_1st_layer = construction.get_referenced_object( 'Outside_Layer') material_2nd_layer = construction.get_referenced_object('Layer_2') # print(material_1st_layer) # print(material_2nd_layer) continue # print(construction) # Change exterior floor construction if ('ext floor' in construction.Name): # print(construction) material_1st_layer = construction.get_referenced_object( 'Outside_Layer') material_2nd_layer = construction.get_referenced_object('Layer_2') material_1st_layer = modify_material_property(material_1st_layer, 'Thickness', times=2) material_2nd_layer = modify_material_property(material_2nd_layer, 'Thickness', times=2) material_1st_layer = modify_material_property(material_1st_layer, 'Conductivity', times=0.5) material_2nd_layer = modify_material_property(material_2nd_layer, 'Conductivity', times=0.5) continue idf.saveas(idf_name_out_1) # 2. Change the window properties for construction in v_constructions: if ('glazing' in construction.Name): material_1st_layer = construction.get_referenced_object( 'Outside_Layer') material_1st_layer = modify_material_property(material_1st_layer, 'UFactor', new_val=6) material_1st_layer = modify_material_property( material_1st_layer, 'Solar_Heat_Gain_Coefficient', new_val=0.8) idf.saveas(idf_name_out_2) # 3. Change the lighting power density for light in v_lights: light['Watts_per_Zone_Floor_Area'] = 18 idf.saveas(idf_name_out_3)
surfaces = idf1.idfobjects['BUILDINGSURFACE:DETAILED'] csurfaces = copy(surfaces) count = 0 print len(surfaces) for surface in csurfaces: s = simplesurface.simplesufrace(idf1, surface, deletebsd=True, setto000=True) if not s: print surface.Name count += 1 print count print len(csurfaces) print len(surfaces) fens = idf1.idfobjects['FENESTRATIONSURFACE:DETAILED'] cfens = copy(fens) print len(fens) count = 0 for fen in cfens: f = simplesurface.simplefenestration(idf1, fen, deletebsd=True, setto000=True) if not f: print fen.Name count += 1 print count print len(cfens) print len(fens) newfname1 = "/Volumes/Server/Staff/Santosh/mike_eplus/working/5ZoneSupRetPlenRAB_flat.idf" idf1.saveas(newfname1)
class Model: """ The environment class. """ model_import_flag = False @classmethod def set_energyplus_folder(cls, path): """ Add the pyenergyplus into the path so the program can find the EnergyPlus. :parameter path: The installation path of the EnergyPlus 9.3.0. :type path: str :return: None """ sys.path.insert(0, path) IDF.setiddname(f"{path}Energy+.idd") cls.model_import_flag = True def __init__(self, idf_file_name: str = None, prototype: str = None, climate_zone: str = None, weather_file: str = None, heating_type: str = None, foundation_type: str = None, agent: Agent = None, reward=None, eplus_naming_dict=None, eplus_var_types=None, buffer_capacity=None, buffer_seed=None, buffer_chkpt_dir=None, tmp_idf_path=None): """ Initialize the building by loading the IDF file to the model. :parameter idf_file_name: The relative path to the IDF file. Use it if you want to use your own model. :parameter prototype: Either "multi" and "single", indicates the Multi-family low-rise apartment building and Single-family detached house. :parameter climate_zone: The climate zone code of the building. Please refer to https://codes.iccsafe.org/content/iecc2018/chapter-3-ce-general-requirements. :parameter weather_file: The relative path to the weather file associate with the building. :parameter heating_type: Select one from "electric", "gas", "oil", and "pump" :parameter foundation_type: Select one from "crawspace", "heated", "slab", and "unheated" :parameter agent: The user-defined Agent class object if the agent is implemented in a class. :parameter reward: The user-defined reward class object that contains a reward(state, actions) method. :parameter eplus_naming_dict: A dictionary map the state variable name to some specified names. :parameter eplus_var_types: A dictionary contains the state name and the state source location. :parameter buffer_capacity: The maximum number of historical state, action, new_state pair store in the buffer. :parameter buffer_seed: The random seed when sample from the buffer. :parameter buffer_chkpt_dir: The location of the buffer checkpoint should save. """ if not Model.model_import_flag: raise ImportError("You have to set the energyplus folder first") self.api = None self.current_state = dict() self.idf = None self.occupancy = None self.run_parameters = None self.queue = EventQueue() self.agent = agent self.ignore_list = set() self.zone_names = None self.thermal_names = None self.counter = 0 self.replay = ReplayBuffer(buffer_capacity, buffer_seed, buffer_chkpt_dir) self.warmup_complete = False self.terminate = False self.wait_for_step = Event() self.wait_for_state = Event() self.parent, self.child_energy = Pipe(duplex=True) self.child = None self.use_lock = False self.reward = reward self.eplus_naming_dict = dict( ) if eplus_naming_dict is None else eplus_naming_dict self.eplus_var_types = dict( ) if eplus_var_types is None else eplus_var_types self.prev_reward = None self.total_timestep = -1 self.leap_weather = False self.state_modifier = StateModifier() # TODO: Validate input parameters if idf_file_name is None and climate_zone is not None: idf_file_name = f"./buildings/{prototype}_{climate_zone}_{heating_type}_{foundation_type}.idf" if weather_file is None and climate_zone is not None: weather_file = f"./weathers/{climate_zone}.epw" if tmp_idf_path is None: self.input_idf = "input.idf" else: self.input_idf = os.path.join(tmp_idf_path, "input.idf") self.run_parameters = ["-d", "result", self.input_idf] if weather_file: self.run_parameters = ["-w", weather_file] + self.run_parameters with open(weather_file, 'r') as w_file: for line in w_file: line = line.split(',') if len(line) > 3 and line[0].upper( ) == "HOLIDAYS/DAYLIGHT SAVINGS": self.leap_weather = True if line[1].upper( ) == "YES" else False break try: self.idf = IDF(idf_file_name) except: raise ValueError( "IDF file is damaged or not match with your EnergyPlus version." ) @staticmethod def name_reformat(name): """ Convert the entry from the space separated entry to the underline separated entry to match the IDF. :parameter name: The space separated entry. :return: The underline separated entry. """ name = name.replace(' ', '_').replace(':', '').split('_') return '_'.join([word for word in name]) def list_all_available_configurations(self): """ Generate a list of all type of components appeared in the current building. :return: list of components entry. """ return list(self.idf.idfobjects.keys()) def get_all_configurations(self): """ Read the IDF file, and return the content formatted with the IDD file. :return: the full IDF file with names and comments aside. """ return self.idf.idfobjects def get_sub_configuration(self, idf_header_name: str): """ Show all available settings for the given type of component. :parameter idf_header_name: The type of the component. :return: List of settings entry. """ idf_header_name = idf_header_name.upper() if not self.idf.idfobjects.get(idf_header_name): raise KeyError(f"No {idf_header_name} section in current IDF file") return self.idf.idfobjects[idf_header_name][0].fieldnames def get_available_names_under_group(self, idf_header_name: str): """ Given the type of components, find all available components in the building by their entry. :parameter idf_header_name: The type of the component. :return: List of names. """ idf_header_name = idf_header_name.upper() available_names = self.get_sub_configuration(idf_header_name) if "Name" in available_names: return [ entry["Name"] for entry in self.idf.idfobjects[idf_header_name] ] else: for field_name in available_names: if "name" in field_name.lower(): return [ entry[field_name] for entry in self.idf.idfobjects[idf_header_name] ] raise KeyError(f"No entry field available for {idf_header_name}") def get_configuration(self, idf_header_name: str, component_name: str = None): """ Given the type of component, the entry of the target component, find the settings of that component. :parameter idf_header_name: The type of the component. :parameter component_name: The entry of the component. :return: Settings of this component. """ idf_header_name = idf_header_name.upper() if component_name is None: return self.idf.idfobjects[idf_header_name] else: names = self.get_available_names_under_group(idf_header_name) if component_name in names: return self.idf.idfobjects[idf_header_name][names.index( component_name)] else: raise KeyError( f"Failed to locate {component_name} in {idf_header_name}") def get_value_range(self, idf_header_name: str, field_name: str, validate: bool = False): """ Get the range of acceptable values of the specific setting. :parameter idf_header_name: The type of the component. :parameter field_name: The setting entry. :parameter validate: Set to True to check the current value is valid or not. :return: Validation result or the range of all acceptable values retrieved from the IDD file. """ idf_header_name = idf_header_name.upper() field_name = field_name.replace(' ', '_') if field_name not in self.get_sub_configuration(idf_header_name): raise KeyError( f"Failed to locate {field_name} in {idf_header_name}") if validate: return self.idf.idfobjects[idf_header_name][0].checkrange( field_name) else: return self.idf.idfobjects[idf_header_name][0].getrange(field_name) def add_configuration(self, idf_header_name: str, values: dict = None): """ Create and add a new component into the building model with the specific type and setting values. :parameter idf_header_name: The type of the component. :parameter values: A dictionary map the setting entry and the setting value. :return: The new component. """ idf_header_name = idf_header_name.upper() object = self.idf.newidfobject(idf_header_name.upper()) if values is None: return object for key, value in values.items(): key = Model.name_reformat(key) if isinstance(value, (int, float)): exec(f"object.{key} = {value}") else: exec(f"object.{key} = '{value}'") return object def delete_configuration(self, idf_header_name: str, component_name: str = None): """ Delete an existing component from the building model. :parameter idf_header_name: The type of the component. :parameter component_name: The entry of the component. :return: None. """ idf_header_name = idf_header_name.upper() if not self.idf.idfobjects.get(idf_header_name): raise KeyError(f"No {idf_header_name} section in current IDF file") if component_name is None: while len(self.idf.idfobjects[idf_header_name]): self.idf.popidfobject(idf_header_name, 0) else: names = self.get_available_names_under_group(idf_header_name) if component_name in names: self.idf.popidfobject(idf_header_name, names.index(component_name)) else: raise KeyError( f"Failed to locate {component_name} in {idf_header_name}") def edit_configuration(self, idf_header_name: str, identifier: dict, update_values: dict): """ Edit an existing component in the building model. :parameter idf_header_name: The type of the component. :parameter identifier: A dictionary map the setting entry and the setting value to locate the target component. :parameter update_values: A dictionary map the setting entry and the setting value that needs to update. :return: None. """ idf_header_name = idf_header_name.upper() if not self.idf.idfobjects.get(idf_header_name): raise KeyError(f"No {idf_header_name} section in current IDF file") fields = self.get_sub_configuration(idf_header_name) for entry in self.idf.idfobjects[idf_header_name]: valid = True for key, value in identifier.items(): key = Model.name_reformat(key) if key in fields: if entry[key] != value: valid = False if valid: for key, value in update_values.items(): key = Model.name_reformat(key) if isinstance(value, (int, float)): exec(f"entry.{key} = {value}") else: exec(f"entry.{key} = '{value}'") def _get_thermal_names(self): """ Initialize all available thermal zones. :return: None """ people_zones = self.get_configuration("People") self.thermal_names = dict() for zone in people_zones: try: if zone[Model.name_reformat("Thermal Comfort Model 1 Type")]: self.thermal_names[zone["Name"]] = zone[ Model.name_reformat("Zone or ZoneList Name")] except BadEPFieldError: pass def save_idf_file(self, path: str): """ Save the modified building model for EnergyPlus simulation :parameter path: The relative path to the modified IDF file. :return: None. """ self.idf.saveas(path) def _initialization(self): """ Initialize the EnergyPlus simulation by letting the EnergyPlus finish the warmup. :return: None """ if not self.api.exchange.api_data_fully_ready(): return self.warmup_complete = True def _generate_output_files(self): """ Assert errors to terminate the simulation after the warmup in order to generate the EDD file to list all available actions for the current building. :return: None """ assert False def _step_callback(self): """ Get the state value at each timestep, and modify the building model based on the actions from the ``EventQueue``. :return: None """ # print("Child: Not ready") if not self.api.exchange.api_data_fully_ready( ) or not self.warmup_complete: return current_state = dict() # print("Child: Simulating") current_state["timestep"] = self.counter # print(self.get_date()) current_state["time"] = self.get_date() current_state["temperature"] = dict() current_state["occupancy"] = dict() current_state["terminate"] = self.total_timestep == self.counter # if self.occupancy is not None: # current_state["occupancy"] = {zone: value[self.counter] for zone, value in self.occupancy.items()} for name in self.zone_names: handle = self.api.exchange.get_variable_handle( "Zone People Occupant Count", name) if handle == -1: continue current_state["occupancy"][ name] = self.api.exchange.get_variable_value(handle) for name in self.zone_names: handle = self.api.exchange.get_variable_handle( "Zone Air Temperature", name) if handle == -1: continue # print("Child: Simulating 2") current_state["temperature"][ name] = self.api.exchange.get_variable_value(handle) handle = self.api.exchange.get_meter_handle("Heating:EnergyTransfer") current_state["energy"] = self.api.exchange.get_meter_value(handle) if self.reward is not None: current_state["reward"] = self.prev_reward # print("Child: Simulating 1") if "Zone Thermal Comfort Fanger Model PMV" in self.get_available_names_under_group( "Output:Variable"): current_state["PMV"] = dict() for zone in self.thermal_names: handle = self.api.exchange.get_variable_handle( "Zone Thermal Comfort Fanger Model PMV", zone) if handle == -1: continue current_state["PMV"][self.thermal_names[ zone]] = self.api.exchange.get_variable_value(handle) # Add state values state_vars = self.get_current_state_variables() # Add for temp extra output for entry in self.idf.idfobjects['OUTPUT:VARIABLE']: # we only care about the output vars for Gnu-RL if (entry['Variable_Name'], entry['Key_Value']) in self.eplus_naming_dict.keys() or \ (entry['Variable_Name'], entry['Key_Value']) in state_vars: var_name = entry['Variable_Name'] # if the key value is not associated with a zone return None for variable handler # key_val = entry['Key_Value'] if entry['Key_Value'] != '*' else None if entry['Key_Value'] == '*': key_val = self.eplus_var_types.get(var_name, None) if key_val is None: continue else: key_val = entry['Key_Value'] handle = self.api.exchange.get_variable_handle( var_name, key_val) if handle == -1: continue # name the state value based on Gnu-RL paper key = self.eplus_naming_dict.get( (var_name, entry['Key_Value']), f"{var_name}_{key_val}") current_state[key] = self.api.exchange.get_variable_value( handle) self.state_modifier.get_update_states(current_state, self) # current_state.update(update_dict) # print(current_state) if self.use_lock: # print("Child: Sending current states") self.child_energy.send(current_state) self.wait_for_state.set() # Take all actions self.wait_for_step.clear() # print("Child: Waiting for actions") if not self.child_energy.poll(): self.wait_for_step.wait() # print("Child: Receiving actions") events = self.child_energy.recv() else: # print(self.current_state) if self.counter != 0: self.replay.push( self.current_state, self.queue.get_event(self.current_state["timestep"]), current_state, current_state["terminate"]) self.current_state = current_state # self.historical_values.append(self.current_state) events = self.queue.trigger(self.counter) self.counter += 1 # Trigger modifiers # for modifier in self.modifier: # modifier.update(current_state) # print("Child: executing actions") # print("Child: Printing Reward") # Calculate Reward if self.reward is not None: self.prev_reward = self.reward.reward(current_state, events) # Trigger events for key in events["actuator"]: component_type, control_type, actuator_key = key.split("|*|") value = events["actuator"][key][1] handle = self.api.exchange.get_actuator_handle( component_type, control_type, actuator_key) if handle == -1: raise ValueError('Actuator handle could not be found: ', component_type, control_type, actuator_key) self.api.exchange.set_actuator_value(handle, value) for key in events["global"]: var_name = key value = events["global"][key][1] handle = self.api.exchange.get_global_handle(var_name) if handle == -1: raise ValueError('Actuator handle could not be found: ', component_type, control_type, actuator_key) self.api.exchange.set_global_value(handle, value) # if self.use_lock: # # wait for next call of step # self.wait_for_step.clear() # self.wait_for_step.wait() # else: if not self.use_lock and self.agent: self.agent.step(self.current_state, self.queue, self.counter - 1) def step(self, action_list=None): """ Add all actions into the ``EventQueue``, and then generate the state value of the next timestep. :parameter action_list: list of dictionarys contains the arguments for ``EventQueue.schedule_event()``. :return: The state value of the current timestep. """ if action_list is not None: for action in action_list: self.queue.schedule_event(**action) # print("Parent: Sending actions") self.parent.send(self.queue.trigger(self.counter)) self.counter += 1 # Let process grab and execute actions # print("Parent: Releasing child's lock") self.wait_for_state.clear() self.wait_for_step.set() # print("Parent: Waiting for state values") if not self.parent.poll(): self.wait_for_state.wait() self.wait_for_state.clear() current_state = self.parent.recv() # if isinstance(current_state, dict): self.replay.push(self.current_state, self.queue.get_event(self.current_state["timestep"]), current_state, current_state["terminate"]) self.current_state = current_state # self.historical_values.append(self.current_state) if current_state["terminate"]: self.terminate = True self.parent.send(self.queue.trigger(self.counter)) self.wait_for_step.set() self.child.join() # self.replay.terminate() self.wait_for_state.clear() # print("Parent: received state values") return self.current_state def is_terminate(self): """ Determine if the simulation is finished or not. :return: True if the simulation is done, and False otherwise. """ return self.terminate def reset(self): """ Clear the actions and buffer, reset the environment and start the simulation. :return: The initial state of the simulation. """ self._init_simulation() self.counter = 0 self.total_timestep = self.get_total_timestep() - 1 self.queue = EventQueue() self.replay.reset() # self.ignore_list = set() self.wait_for_state.clear() self.wait_for_step.clear() self.terminate = False self.use_lock = True self.parent, self.child_energy = Pipe(duplex=True) self.child = Process(target=self.simulate) self.child.start() # print("Waiting") if not self.parent.poll(): self.wait_for_state.wait() self.current_state = self.parent.recv() # self.historical_values.append(self.current_state) self.wait_for_state.clear() return self.current_state def get_total_timestep(self): if "-w" not in self.run_parameters: return self.get_configuration( "Timestep")[0].Number_of_Timesteps_per_Hour * 24 * 8 elif len(self.get_configuration("RunPeriod")) == 0: raise ValueError( "Your IDF files does not specify the run period." "Please manually edit the IDF file or use Model().set_runperiod(...)" ) run_period = self.get_configuration("RunPeriod")[0] start = datetime( year=run_period.Begin_Year if run_period.Begin_Year else 2000, month=run_period.Begin_Month, day=run_period.Begin_Day_of_Month) end = datetime( year=run_period.End_Year if run_period.End_Year else start.year, month=run_period.End_Month, day=run_period.End_Day_of_Month) end += timedelta(days=1) if not self.leap_weather: offset = 0 for year in range(start.year, end.year + 1): if isleap(year) and datetime(year, 2, 29) > start and datetime( year, 2, 29) < end: offset += 1 end -= timedelta(days=offset) timestep = self.get_configuration( "Timestep")[0].Number_of_Timesteps_per_Hour if 60 % timestep != 0: timestep = 60 // round(60 / timestep) return int((end - start).total_seconds() // 3600 * timestep) def simulate(self, terminate_after_warmup=False): """ Run the whole simulation once. If user use this method instead of the reset function, the user need to provide the Agent. :parameter terminate_after_warmup: True if the simulation should terminate after the warmup. :return: None. """ from pyenergyplus.api import EnergyPlusAPI self.replay.set_ignore(self.state_modifier.get_ignore_by_checkpoint()) if not self.use_lock: self._init_simulation() # for entry in self.zone_names: # print(entry) # self.current_handle["temperature"][entry] = \ # self.api.exchange.get_variable_handle("Zone Air Temperature", entry) # self.current_handle["temperature"] = self.api.exchange.get_variable_handle("SITE OUTDOOR AIR DRYBULB TEMPERATURE", "ENVIRONMENT") # self.current_handle["energy"] = self.api.exchange.get_meter_handle("Electricity:Facility") self.api = EnergyPlusAPI() if not terminate_after_warmup: self.api.runtime.callback_after_new_environment_warmup_complete( self._initialization) self.api.runtime.callback_begin_system_timestep_before_predictor( self._step_callback) else: self.api.runtime.callback_begin_new_environment( self._generate_output_files) self.api.runtime.run_energyplus(self.run_parameters) # if self.use_lock: # self.child_energy.send("Terminated") # self.wait_for_state.set() # else: # self.replay.terminate() def _init_simulation(self): """ Save the modified building model and initialize the zones for states. :return: None. """ try: self.get_configuration("Output:Variable", "Zone People Occupant Count") except KeyError: self.add_configuration( "Output:Variable", { "Key Value": '*', "Variable Name": "Zone People Occupant Count", "Reporting Frequency": "Timestep" }) self.idf.saveas(self.input_idf) self.use_lock = False self.zone_names = self.get_available_names_under_group("Zone") self._get_thermal_names() self.warmup_complete = False def get_current_state_variables(self): """ Find the current entries in the state. :return: List of entry names that is currently available in the state. """ state_values = list( set(self.get_possible_state_variables()) - self.ignore_list) state_values.sort() return state_values def select_state_variables(self, entry=None, index=None): """ Select interested state entries. If selected entry is not available for the current building, it will be ignored. :parameter entry: Entry names and corresponding objects that the state of the environment should have. :parameter index: Index of all available entries that the state of the environment should have. :return: None. """ current_state = self.get_current_state_variables() if entry is None: entry = list() elif isinstance(entry, tuple): entry = list(entry) if index is not None: if isinstance(index, int): index = [index] for i in index: if i < len(current_state): entry.append(current_state[i]) self.ignore_list = set( self.get_possible_state_variables()) - set(entry) def add_state_variables(self, entry): """ Add entries to the state. If selected entry is not available for the current building, it will be ignored. :parameter entry: Entry names and corresponding objects that the state of the environment should have. :return: None. """ if not self.ignore_list: return if isinstance(entry, tuple): entry = [entry] self.ignore_list -= set(entry) def remove_state_variables(self, entry): """ Remove entries from the state. If selected entry is not available in the state, it will be ignored. :parameter entry: Entry names and corresponding objects that the state of the environment should not have. :return: None. """ if isinstance(entry, tuple): entry = [entry] self.ignore_list = self.ignore_list.union(set(entry)) def pop_state_variables(self, index): """ Remove entries from the state by its index. If selected index is not available in the state, it will be ignored. :parameter index: Entry index that the state of the environment should not have. :return: All entry names that is removed. """ current_state = self.get_current_state_variables() pop_values = list() if isinstance(index, int): index = [index] for i in index: if i < len(current_state): self.ignore_list.add(current_state[i]) pop_values.append(current_state[i]) return pop_values def get_possible_state_variables(self): """ Get all available state entries. This list of entries only depends on the building architecture. :return: List of available state entry names. """ output = [(var["Variable_Name"], var["Key_Value"]) for var in self.get_configuration("Output:Variable") if var["Key_Value"] != "*"] output.sort() return output def get_possible_actions(self): """ Get all available actions that the user-defined agent can take. This list of actions only depends on the building architecture. :return: List of available actions in dictionaries. """ if not os.path.isfile("./result/eplusout.edd"): if not self.get_configuration("Output:EnergyManagementSystem"): self.add_configuration( "Output:EnergyManagementSystem", values={ "Actuator Availability Dictionary Reporting": "Verbose", "Internal Variable Availability Dictionary Reporting": "Verbose", "EMS Runtime Language Debug Output Level": "ErrorsOnly" }) try: self.simulate(terminate_after_warmup=True) except AssertionError: pass actions = list() with open("./result/eplusout.edd", 'r') as edd: for line in edd: line = line.strip() if len(line) == 0 or line[0] == '!': continue line = line.split(',') actions.append({ "Component Type": line[2], "Control Type": line[3], "Actuator Key": line[1] }) return actions def get_link_zones(self): """ Generate a graph that shows the connectivity of zones of the current building. :return: A bi-directional graph represented by a dictionary where the key is the source zone name and the value is a set of all neighbor zone name. """ link_zones = {"Outdoor": set()} wall_to_zone = {} walls = self.get_configuration("BuildingSurface:Detailed") for wall in walls: if wall.Surface_Type != "WALL": continue wall_to_zone[wall.Name] = wall.Zone_Name link_zones[wall.Zone_Name] = set() for wall in walls: if wall.Surface_Type != "WALL": continue if wall.Outside_Boundary_Condition == "Outdoors": link_zones[wall.Zone_Name].add("Outdoor") link_zones["Outdoor"].add(wall.Zone_Name) elif wall.Outside_Boundary_Condition_Object: link_zones[wall_to_zone[ wall.Outside_Boundary_Condition_Object]].add( wall.Zone_Name) link_zones[wall.Zone_Name].add( wall_to_zone[wall.Outside_Boundary_Condition_Object]) return link_zones def get_date(self): """ Get the current time in the simulation environment. :return: None """ year = self.api.exchange.year() month = self.api.exchange.month() day = self.api.exchange.day_of_month() hour = self.api.exchange.hour() minute = self.api.exchange.minutes() current_time = datetime(year, month, day, hour) + timedelta(minutes=minute) return current_time def get_windows(self): """ Get the zone-window matching dictionary based on the IDF file. :return: A dictionary where key is the zone name, and the value is a set of window available in the zone. """ zone_window = { name: set() for name in self.get_available_names_under_group("Zone") } all_window = dict() for window in self.get_configuration("FenestrationSurface:Detailed"): if window.Surface_Type != "WINDOW": continue all_window[window.Building_Surface_Name] = window.Name for wall in self.get_configuration("BuildingSurface:Detailed"): if wall.Surface_Type != "WALL": continue if wall.Name in all_window: zone_window[wall.Zone_Name].add(all_window[wall.Name]) return zone_window def get_doors(self): """ Get the zone-door matching dictionary based on the IDF file. :return: A dictionary where key is the zone name, and the value is a set of door available in the zone. """ zone_door = { name: set() for name in self.get_available_names_under_group("Zone") } all_door = dict() for door in self.get_configuration("FenestrationSurface:Detailed"): if door.Surface_Type != "GLASSDOOR": continue all_door[door.Building_Surface_Name] = door.Name for wall in self.get_configuration("BuildingSurface:Detailed"): if wall.Surface_Type != "WALL": continue if wall.Name in all_door: zone_door[wall.Zone_Name].add(all_door[wall.Name]) return zone_door def get_lights(self): """ Get the zone-light matching dictionary based on the IDF file. :return: A dictionary where key is the zone name, and the value is a set of light available in the zone. """ zone_light = { name: set() for name in self.get_available_names_under_group("Zone") } for light in self.get_configuration("Lights"): zone_light[light.Zone_or_ZoneList_Name].add(light.Name) return zone_light def get_blinds(self): """ Get the zone-blind matching dictionary based on the IDF file. :return: A dictionary where key is the zone name, and the value is a set of blind available in the zone. """ window_with_blinds = set() for shade in self.get_configuration("WindowShadingControl"): window_with_blinds.add(shade.Fenestration_Surface_1_Name) zone_blinds = self.get_windows() for zone in zone_blinds: zone_blinds[zone] = zone_blinds[zone].intersection( window_with_blinds) return zone_blinds def set_blinds(self, windows, blind_material_name=None, shading_control_type='AlwaysOff', setpoint=50, agent_control=False): """ Install blinds that can be controlled on some given windows. :param windows: An iterable object that includes all windows' name that plan to install the blind. :param blind_material_name: The name of an existing blind in the IDF file as the blind for all windows. :param shading_control_type: Specify default EPlus control strategy (only works if control=False) :param setpoint: Specify default blind angle. :param agent_control: False if using a default EPlus control strategy or no control (ie blinds always off). True if using an external agent to control the blinds. :return: None """ if agent_control: shading_control_type = 'OnIfScheduleAllows' blind_material = None if blind_material_name: try: blind_material = self.get_configuration( "WindowMaterial:Blind", blind_material_name) except KeyError: pass zone_window = self.get_windows() for zone in zone_window: for window in zone_window[zone]: if window in windows: window_idf = self.get_configuration( "FenestrationSurface:Detailed", window) if blind_material is None: blind = { "Name": f"{window}_blind", "Slat Orientation": "Horizontal", "Slat Width": 0.025, "Slat Separation": 0.01875, "Front Side Slat Beam Solar Reflectance": 0.8, "Back Side Slat Beam Solar Reflectance": 0.8, "Front Side Slat Diffuse Solar Reflectance": 0.8, "Back Side Slat Diffuse Solar Reflectance": 0.8, "Slat Beam Visible Transmittance": 0.0 } blind_mat = self.add_configuration( "WindowMaterial:Blind", values=blind) else: blind_mat = self.idf.copyidfobject(blind_material) blind_mat.Name = blind_mat.Name + f" {window}" shading = { "Name": f"{window}_blind_shading", "Zone Name": zone, "Shading Type": "InteriorBlind", "Shading Device Material Name": f"{blind_mat.Name}", "Shading Control Type": shading_control_type, "Setpoint": setpoint, "Type of Slat Angle Control for Blinds": "ScheduledSlatAngle", "Fenestration Surface 1 Name": window_idf.Name } if agent_control: shading[ "Slat Angle Schedule Name"] = f"{window}_shading_schedule" shading["Multiple Surface Control Type"] = "Group" shading["Shading Control Is Scheduled"] = "Yes" angle_schedule = { "Name": f"{window}_shading_schedule", "Schedule Type Limits Name": "Angle", "Hourly Value": 45 } self.add_configuration("Schedule:Constant", values=angle_schedule) self.add_configuration("WindowShadingControl", values=shading) def set_occupancy(self, occupancy, locations): """ Include the occupancy schedule generated by the OccupancyGenerator to the model as the occupancy data in EnergyPlus simulated environment is broken. :param occupancy: Numpy matrix contains the number of occupanct in each zone at each time slot. :param locations: List of zone names. :return: None """ occupancy = occupancy.astype(int) self.occupancy = { locations[i]: occupancy[i, :] for i in range(len(locations)) } if "Outdoor" in self.occupancy.keys(): self.occupancy.pop("Outdoor") if "busy" in self.occupancy.keys(): self.occupancy.pop("busy") def set_runperiod(self, days, start_year: int = 2000, start_month: int = 1, start_day: int = 1, specify_year: bool = False): """ Set the simulation run period. :param days: How many days in total the simulation should perform. :param start_year: Start from which year :param start_month: Start from which month of the year :param start_day: Start from which day of the month :param specify_year: Use default year or a specific year when simulation is within a year. :return: None """ if "-w" not in self.run_parameters: raise KeyError("You must include a weather file to set run period") start = datetime(start_year, start_month, start_day) end = start + timedelta(days=days - 1) if not self.leap_weather: test_year = start_year - 1 while datetime(test_year, 1, 1) < end: test_year += 1 if not isleap(test_year): continue if datetime(test_year, 2, 29) > start and datetime( test_year, 2, 29) < end: end += timedelta(days=1) values = { "Begin Month": start_month, "Begin Day of Month": start_day, "End Month": end.month, "End Day of Month": end.day } if end.year != start_year or specify_year: values.update({"Begin Year": start_year, "End Year": end.year}) run_setting = self.get_configuration("RunPeriod") if len(run_setting) == 0: values["Name"] = "RunPeriod 1" self.add_configuration("RunPeriod", values) else: name = self.get_configuration("RunPeriod")[0].Name self.edit_configuration("RunPeriod", {"Name": name}, values) def set_timestep(self, timestep_per_hour): """ Set the timestep per hour for the simulation. :param timestep_per_hour: How many timesteps within a hour. :return: None """ self.get_configuration( "Timestep")[0].Number_of_Timesteps_per_Hour = timestep_per_hour def add_state_modifier(self, model): """ Add a state modifier model, including predictive model, state estimator, controller, etc. :param model: A class object that follows the template (contains step(true_state, environment) method). :return: None """ self.state_modifier.add_model(model) def flatten_state(self, order, state=None): """ Flatten the state to a list of values by a given order. :param order: The order that the values should follow. :param state: The state to flatten. If not specified, then the current state is selected. :return: List of values follows the given order. """ if state is None: state = self.current_state return [self.current_state.get(name, None) for name in order] def sample_buffer(self, batch_size): """ Sample a batch of experience from the replay buffer. :param batch_size: Number of entries in a batch. :return: (state, action, next state, is terminate) """ return self.replay.sample(batch_size) def sample_flattened_buffer(self, order, batch_size): """ Sample a batch of experience from the replay buffer and flatten the states by a given order. :param order: The order that the values should follow. :param batch_size: Number of entries in a batch. :return: (state, action, next state, is terminate) where states are flatten. """ state, action, next_state, done = self.replay.sample(batch_size) for i, row in state: state[i] = self.flatten_state(order, row) for i, row in next_state: next_state[i] = self.flatten_state(order, row) return state, action, next_state, done
def prepare_LP_plantloop(expanded_plant_loop_idf='expanded.idf', LP_plant_loop_idf='plant_loop.idf', idd_file="C:/EnergyPlusV9-1-0/Energy+.idd"): # constants BRANCH_TO_DELETE = [ 'Test room Cooling Coil ChW Branch', 'Test room Heating Coil HW Branch' ] DEMAND_BRANCH_LISTS = [ 'Hot Water Loop HW Demand Side Branches', 'Chilled Water Loop ChW Demand Side Branches' ] DEMAND_SPLITTER_LISTS = [ 'Hot Water Loop HW Demand Splitter', 'Chilled Water Loop ChW Demand Splitter' ] DEMAND_MIXER_LISTS = [ 'Hot Water Loop HW Demand Mixer', 'Chilled Water Loop ChW Demand Mixer' ] OLD_HW_LP_BRANCH_NAME = 'Test room Heating Coil HW Branch' OLD_CW_LP_BRANCH_NAME = 'Test room Cooling Coil ChW Branch' NEW_HW_LP_BRANCH_NAME = 'Hot Water Loop Load Profile Demand Branch' NEW_CW_LP_BRANCH_NAME = 'Chilled Water Loop Load Profile Demand Branch' idf_file = expanded_plant_loop_idf IDF.setiddname(idd_file) idf = IDF(idf_file) branches = idf.idfobjects['Branch'] branche_lists = idf.idfobjects['BranchList'] splitter_lists = idf.idfobjects['Connector:Splitter'] mixer_lists = idf.idfobjects['Connector:Mixer'] # 1. Remove unnecessary objects def remove_all_obj_by_type(idf, obj_type_name, exception_name_list=[]): if exception_name_list == []: idf.idfobjects[obj_type_name] = [] else: old_objcts = idf.idfobjects[obj_type_name] idf.idfobjects[obj_type_name] = [ obj for obj in old_objcts if obj.Name in exception_name_list ] return idf remove_all_obj_by_type(idf, 'Sizing:Parameters') remove_all_obj_by_type(idf, 'ScheduleTypeLimits', ['HVACTemplate Any Number']) remove_all_obj_by_type( idf, 'Schedule:Compact', ['HVACTemplate-Always 1', 'HVACTemplate-Always 29.4']) remove_all_obj_by_type(idf, 'DesignSpecification:OutdoorAir') remove_all_obj_by_type(idf, 'Sizing:Zone') remove_all_obj_by_type(idf, 'DesignSpecification:ZoneAirDistribution') remove_all_obj_by_type(idf, 'ZoneHVAC:EquipmentConnections') remove_all_obj_by_type(idf, 'ZoneHVAC:EquipmentList') remove_all_obj_by_type(idf, 'ZoneHVAC:FourPipeFanCoil') remove_all_obj_by_type(idf, 'ZoneControl:Thermostat') remove_all_obj_by_type(idf, 'Fan:SystemModel') remove_all_obj_by_type(idf, 'OutdoorAir:Mixer') remove_all_obj_by_type(idf, 'OutdoorAir:NodeList') remove_all_obj_by_type(idf, 'Coil:Cooling:Water') remove_all_obj_by_type(idf, 'Coil:Heating:Water') remove_all_obj_by_type(idf, 'Output:PreprocessorMessage') # 2. Delete the old zone coil branch objects new_branches = [ branch for branch in branches if branch.Name not in BRANCH_TO_DELETE ] idf.idfobjects['Branch'] = new_branches # 3. Rename the demand branches from zone coil branch to load profile branch in the BranchList and Mixer/Splitter objects for branch_list in branche_lists: if branch_list.Name in DEMAND_BRANCH_LISTS: if branch_list.Branch_2_Name == OLD_HW_LP_BRANCH_NAME: branch_list.Branch_2_Name = NEW_HW_LP_BRANCH_NAME elif branch_list.Branch_2_Name == OLD_CW_LP_BRANCH_NAME: branch_list.Branch_2_Name = NEW_CW_LP_BRANCH_NAME for splitter in splitter_lists: if splitter.Name in DEMAND_SPLITTER_LISTS: if splitter.Outlet_Branch_2_Name == OLD_HW_LP_BRANCH_NAME: splitter.Outlet_Branch_2_Name = NEW_HW_LP_BRANCH_NAME if splitter.Outlet_Branch_2_Name == OLD_CW_LP_BRANCH_NAME: splitter.Outlet_Branch_2_Name = NEW_CW_LP_BRANCH_NAME for mixer in mixer_lists: if mixer.Name in DEMAND_MIXER_LISTS: if mixer.Inlet_Branch_2_Name == OLD_HW_LP_BRANCH_NAME: mixer.Inlet_Branch_2_Name = NEW_HW_LP_BRANCH_NAME if mixer.Inlet_Branch_2_Name == OLD_CW_LP_BRANCH_NAME: mixer.Inlet_Branch_2_Name = NEW_CW_LP_BRANCH_NAME # 4. Save the idf. idf.saveas(LP_plant_loop_idf)
def delete_cmplx_HVAC_keep_DHW(originalidf_path,savefolder_path): """ An advanced automatic version of the delete_cmplx_HVAC() in version 1.0. Now it is possible to seperate DHW and HVAC systems without manual intervention The only requirement is that DHW elements should have an identifier, or common string throughout. This could be "DHW" or "SHW" or any other string portion that is used repeatedly in all DHW objects. Run Order: 1) Identify HVAC keys in IDF 2) Getting objects from the HVAC keys 3) Searching for DHW objects 4) Deleting all HVAC keys 5) Recreating DHW objects and defining into the IDF :param originalidf_path: Path for the original IDF with a complex HVAC data :param savefolder_path: Path to use where all converted files will be saved :return: """ # Backup originalidf = IDF(originalidf_path) building=originalidf.idfobjects["Building".upper()][0].Name originalidf.saveas(f"{savefolder_path}\\{building}_BuildME_interim.idf") idf=IDF(f"{savefolder_path}\\{building}_BuildME_interim.idf") name=input(colored(0, 255, 255, "Please enter str value for the common DHW naming used in your IDF file:")) # Lets find out all available keys in the IDF file allkeys = idfobjectkeys(idf) # Getting all possible HVAC-related keys by filtering... HVAC_related_list= allkeys[allkeys.index('HVACTEMPLATE:THERMOSTAT'):] HVAC_related_list = HVAC_related_list[:HVAC_related_list.index('MATRIX:TWODIMENSION')] findDHWlist=HVAC_related_list # Gathering all objects individually in our HVAC list and creating a homogenous list list=[] for items in findDHWlist: HVACobjects=idf.idfobjects[items.upper()] for obj in HVACobjects: list.append(obj) # Finding all DHW fields and their corresponding overarching objects objectswithDHW = [] allparameterfields=[] for newobj in list: for fields in newobj.fieldnames: if newobj[fields]!="": if type(newobj[fields])==str: if name in newobj[fields]: allparameterfields.append(newobj[fields]) objectswithDHW.append(newobj) # Deleting all HVAC and DHW objects in our filtered list for HVAC_obj in HVAC_related_list: idf.removeallidfobjects(HVAC_obj) # Recreating DHW elements objectswithDHW_reduced=reduce(lambda l, x: l.append(x) or l if x not in l else l, objectswithDHW, []) for newobjects in objectswithDHW_reduced: idf.copyidfobject(newobjects) idf.saveas(f"{savefolder_path}\\{building}_BuildME_cleaned.idf") editedidf=idf return editedidf
class EpisodicModel: model_import_flag = False # TODO - user should define actions outside of the model # EnergyManagementSystem:Actuator Available, # VAV SYS 1 OUTLET NODE, # System Node Setpoint, # Temperature Setpoint,[C] component_type = "System Node Setpoint" control_type = "Temperature Setpoint" actuator_key = "VAV SYS 1 OUTLET NODE" # EnergyManagementSystem:Actuator Available, # SEASONAL RESET SUPPLY AIR TEMP SCH, # Schedule:Compact, # Schedule Value # component_type = "Schedule:Compact" # control_type = "Schedule Value" # actuator_key = "SEASONAL RESET SUPPLY AIR TEMP SCH" component_type = "Schedule:Constant" control_type = "Schedule Value" actuator_key = "SAT_SP" @classmethod def set_energyplus_folder(cls, path): sys.path.insert(0, path) IDF.setiddname(f"{path}Energy+.idd") cls.model_import_flag = True def __init__( self, idf_file_name: str, weather_file: str, year: int, step: int, eplus_naming_dict: dict, eplus_var_types: dict, state_name: list = None, max_episodes: int = None, max_episode_steps: int = None, agent: Agent = None, ): """ Refer to EMS application guide: https://bigladdersoftware.com/epx/docs/9-3/ems-application-guide/ems-calling-points.html#ems-calling-points for infomration on control flow :param idf_file_name: The path to the idf file :param weather_file: The path to the epw file :param tol_eps: An integer representing the total amount of episodes :param n_step: An integer representing the max number of steps per episode :param agent: An agent object. Used for control. """ # Setup Energy Plus self.api = None self.year = year if not EpisodicModel.model_import_flag: raise ImportError("You have to set the energyplus folder first") self.run_parameters = ["-d", "result", "input.idf"] if weather_file: self.run_parameters = ["-w", weather_file] + self.run_parameters try: self.idf = IDF(idf_file_name) except Exception: raise ValueError( "IDF file is damaged or not match with your EnergyPlus version." ) # Flags for completed warmups: based on EMS documentation self.warmup_design_complete = False self.warmup_run_complete = False self.after_warmup_call_num = 1 self.warmup_complete = False # Set Agent and controller vars self.agent = agent self.last_action = None self.last_state = None self.total_reward = 0 self.state_name = state_name self.start_time = None self.step = step # self.queue = EventQueue() # Set Episodic Variables self.max_episodes = max_episodes self.max_episode_steps = max_episode_steps self.i_episode = 0 self.i_episode_step = 0 self.i_timestep = 0 # set dicts to control energy plus naming self.eplus_naming_dict = eplus_naming_dict self.eplus_var_types = eplus_var_types def get_date(self): year = self.year month = self.api.exchange.month() day = self.api.exchange.day_of_month() hour = self.api.exchange.hour() minute = self.api.exchange.minutes() return year, month, day, hour, minute def get_observation(self): obs_dict = {} for entry in self.idf.idfobjects['OUTPUT:VARIABLE']: # we only care about the output vars for Gnu-RL if (entry['Variable_Name'], entry['Key_Value']) in self.eplus_naming_dict.keys(): var_name = entry['Variable_Name'] # if the key value is not associated with a zone return None for variable handler # key_val = entry['Key_Value'] if entry['Key_Value'] != '*' else None if entry['Key_Value'] == '*': key_val = self.eplus_var_types[var_name] else: key_val = entry['Key_Value'] handle = self.api.exchange.get_variable_handle( var_name, key_val) # name the state value based on Gnu-RL paper key = self.eplus_naming_dict.get( (var_name, entry['Key_Value'])) obs_dict[key] = self.api.exchange.get_variable_value(handle) state = torch.tensor([obs_dict[name] for name in self.state_name ]).unsqueeze(0).double() if self.start_time is None: self.start_time = pd.datetime(year=self.year, month=self.api.exchange.month(), day=self.api.exchange.day_of_month()) cur_time = self.start_time else: cur_time = self.start_time + pd.Timedelta(seconds=self.step * (self.i_timestep + 1)) observation = (state, obs_dict, obs_dict, cur_time) return observation def get_reward(self, obs_dict): reward = r_func(obs_dict, self.last_action, self.agent.learner.eta) return reward def is_terminal(self): return self.i_episode_step == (self.max_episode_steps - 1) # if self.i_episode_step == (self.max_episode_steps-1): # return True # else: # return False # def trigger_events(self): # events = self.queue.trigger(self.i_timestep) # for key in events["actuator"]: # component_type, control_type, actuator_key = key.split("|*|") # value = events["actuator"][key][1] # handle = self.api.exchange.get_actuator_handle(component_type, control_type, actuator_key) # self.api.exchange.set_actuator_value(handle, value) # for key in events["global"]: # var_name = key # value = events["global"][key][1] # handle = self.api.exchange.get_global_handle(var_name) # self.api.exchange.set_global_value(handle, value) def env_make(self): """ Wait until the warmup periods are complete before starting simulation """ if not self.api.exchange.api_data_fully_ready(): return self.warmup_complete = True self.last_state = self.get_observation() def env_reset(self): """ Resets the environment and returns an initial observation In our episodic case every episode is a day, so the environment is not reset. The initial observation just needs to be returned. """ if not self.api.exchange.api_data_fully_ready(): return if not self.warmup_complete: return if self.i_episode >= self.max_episodes: return if self.i_episode_step == 0: self.last_action = self.agent.agent_start(self.last_state, self.i_episode) def env_action(self): """ Trigger actions using EMS actuators """ if not self.api.exchange.api_data_fully_ready(): return if not self.warmup_complete: return if self.i_episode >= self.max_episodes: return action, SAT_stpt = self.last_action handle = self.api.exchange.get_actuator_handle(self.component_type, self.control_type, self.actuator_key) if handle == -1: raise ValueError('Actuator handle could not be found') self.api.exchange.set_actuator_value(handle, SAT_stpt) # self.queue.schedule_event(SAT_stpt, self.i_timestep+1, 0, # component_type=component_type, # control_type=control_type, # actuator_key=actuator_key) # # self.trigger_events() def env_step(self): """ Takes an action and triggers agent afterwards Returns: observation: object reward: float done: boolean info: dict """ if not self.api.exchange.api_data_fully_ready(): return if not self.warmup_complete: return if self.i_episode >= self.max_episodes: return self.last_state = self.get_observation() handle_act = self.api.exchange.get_actuator_handle( self.component_type, self.control_type, self.actuator_key) val_act = self.api.exchange.get_actuator_value(handle_act) handle_obv = self.api.exchange.get_variable_handle( 'System Node Temperature', 'VAV SYS 1 OUTLET NODE') val_obvs = self.api.exchange.get_variable_value(handle_obv) # print(val_act, val_obvs, self.last_state[1]['Indoor Temp.']) # pdb.set_trace() reward = self.get_reward(self.last_state[1]) term = self.is_terminal() handle = self.api.exchange.get_actuator_handle(self.component_type, self.control_type, self.actuator_key) val = self.api.exchange.get_actuator_value(handle) # print('actuator value in step function', val) if term: self.agent.agent_end(reward, self.last_state, self.i_episode) self.i_episode += 1 self.i_episode_step = 0 else: self.last_action = self.agent.agent_step(reward, self.last_state) self.i_episode_step += 1 self.i_timestep += 1 def simulate(self): from pyenergyplus.api import EnergyPlusAPI self.idf.saveas("input.idf") self.api = EnergyPlusAPI() self.api.runtime.callback_after_new_environment_warmup_complete( self.env_make) self.api.runtime.callback_begin_system_timestep_before_predictor( self.env_reset) # self.api.runtime.callback_begin_zone_timestep_before_init_heat_balance(self.env_action) # self.api.runtime.callback_after_predictor_before_hvac_managers(self.env_action) self.api.runtime.callback_begin_system_timestep_before_predictor( self.env_action) self.api.runtime.callback_end_zone_timestep_after_zone_reporting( self.env_step) status = self.api.runtime.run_energyplus(self.run_parameters) print('Simulator return status: ', status)
# <markdowncell> # This is easy: # <codecell> idf1.save() # <markdowncell> # If you'd like to do a "Save as..." use this: # <codecell> idf1.saveas("something.idf") # <headingcell level=2> # Working with E+ objects # <markdowncell> # Let us open a small idf file that has only "CONSTRUCTION" and "MATERIAL" objects in it. You can go into "../idffiles/V_7_2/constructions.idf" and take a look at the file. We are not printing it here because it is too big. # # So let us open it using the idfreader - # <codecell> from eppy import modeleditor from eppy.modeleditor import IDF
# In[2]: IDF.setiddname(iddfile) idf1 = IDF(fname1) # In[3]: idf1 = IDF(fname1) # In[4]: idf1.saveas("bl_original.idf") # In[5]: keys = list(idf1.idfobjects.keys()) # In[6]: # rename object name with a colon and any field that refers to that name from eppy.bunch_subclass import BadEPFieldError renamednames = [] for key in keys: for idfobject in idf1.idfobjects[key]: try:
def create_idf_file( input_file_path, iddfile, nbiterations, baselineIDF, versionIDF, pathnameto_eppy=r'C:/Users/mkj32/Documents/2016-2019 PhD/School Theoretical/Energy Plus/IdealLoads' ): """creates idf based on baseline IDF, and three inputs: file path to baseline IDF, pathname to EnergyPlus Package, and nb of iterations to run the simulation i.e. number of simulations based on the uncertainty input file.""" printversionIDF(versionIDF) # Using the user defined function # Prepare the idd file and file paths IDF.setiddname(iddfile) os.chdir(input_file_path) # Three possibilities of window to wall ratio # baselineIDF = pathnameto_eppy+r'/baseline_V890.idf' idfname_wwr1 = pathnameto_eppy + r'/FenestrationSurface_WWR_1.idf' idfname_wwr2 = pathnameto_eppy + r'/FenestrationSurface_WWR_2.idf' idfname_wwr3 = pathnameto_eppy + r'/FenestrationSurface_WWR_3.idf' idf_baseline_wwr = [idfname_wwr1, idfname_wwr2, idfname_wwr3] # Load all the input files zonename = pd.read_csv("zonename.csv") allzones = pd.read_csv("zonetype.csv") heatgains = pd.read_csv("heatgains.csv") uncertainty = pd.read_csv("uncertainty_NoDaylighting_raw.csv") daylighting_refpoints = pd.read_csv("daylightingcontrol_refpoints.csv") scheduletime = pd.read_csv( "scheduletimes_on_avoiderror.csv" ) #removed store and toilet equipment schedule as it was already present in basefile idfwindowfile = pathnameto_eppy + r'/TopSouthClassroom_RoofWindow.idf' Equipment_sch = scheduletime[scheduletime.ScheduleType == "Equipment"] Ventilation_sch = scheduletime[scheduletime.ScheduleType == "Ventilation"] Heat_sch = scheduletime[scheduletime.ScheduleType == "Heat"] for runindex, run in uncertainty.head( n=nbiterations).iterrows(): # only run for the first iteration wallC, roofC, groundC, Infil = calc_wall_prop( run) # load wall properties from calc_wall_property function daylighting = run.DaylightingControl Schedule = run.schedule Boiler = run.BoilerEfficiency heating = run.HeatingSP # heating setpoint operative temperature ventilation = run.ventilation # 0 means no ventilation while 1 means full ventilation, ventilation schedule only 0 or 1. wwr = run.WWR # window wall ratio; wwr 1 means 20, 2 means 40, 3 means 60 only for classroom idf1 = IDF(baselineIDF) ## ..........................IDF FILE BASED ON WWR............................................ for wwr_test in range(1, 4): #creates a dummy value equal to 1, 2 or 3 if wwr == wwr_test: #checks if the WWR is 1, 2 or 3 print(wwr) fenestrationfile = idf_baseline_wwr[wwr_test - 1] add_window_component( idf1, fenestrationfile ) # assigns the correct IDF file for the corresponding WWR value ## ..........................MATERIALS..................................................... # make four new materials with the specified u values and ratios above materials = idf1.idfobjects["MATERIAL"] for i in range(0, 3): idf1.newidfobject("MATERIAL") # add three empty materials for material in materials: if material.Name == "": material.Roughness = "MediumRough" material.Thickness = 0.508 material.Density = 43 material.Specific_Heat = 1210 materials[len(materials) - 3].Name = "wall insulation" materials[len(materials) - 3].Conductivity = wallC materials[len(materials) - 2].Name = "ground insulation" materials[len(materials) - 2].Conductivity = groundC materials[len(materials) - 1].Name = "roof insulation" materials[len(materials) - 1].Conductivity = roofC # make window glazing: windowglazing = idf1.newidfobject("WINDOWMATERIAL:SIMPLEGLAZINGSYSTEM") windowglazing.Name = "simple window" windowglazing.UFactor = run.WinU windowglazing.Solar_Heat_Gain_Coefficient = run.WinSHGC ## ..........................INPUT OF CONDITIONAL DAYLIGHTING CONTROLS..................................................... # Add branch and branch list information if daylighting == 1: # Add daylighting control to idf, conditionally on daylighting being = 1 for zoneindex, zone in daylighting_refpoints.iterrows(): print(zoneindex) daylighting_control( idf1, zone, zoneindex ) # this inputs daylighting control and reference point # from the daylighting_controls_on csv file if run.roofwindow == 1: add_window_component(idf1, idfwindowfile) addco2(idf1, 400, 500) ## ..........................ZONE PROPERTIES..................................................... # Create a for loop with all the info for each zone for zoneindex, zone in allzones.iterrows(): zonename = zone.zonename zonetype = zone.type typecode = zone.typecode for roomindex, hg in heatgains.iterrows(): zonetype2 = hg.zonetype if zonetype == zonetype2: equip = hg.equipment lighting = hg.lightingW occupancy = hg.occupancy meta = hg.metabolicWPerson latent = hg.LatentGains heating = hg.heating heatingsetback = hg.heatingsetback ventilationrate = hg.ventilation * ventilation / 1000.0 #change unit from l/s to m3/s per person for ventilation #schedules: schequip = hg.equipmentSchl schheat = hg.heatSchl schlight = hg.lightSchl schoccu = hg.occupancySchl schventilation = hg.ventilationSchl #print(zoneindex,zonename, zonetype, typecode, equip,lighting, people,meta,schoccu) # Create a new object for the zone: idf1.newidfobject( "PEOPLE") #everytime you do that you add a new empty material idf1.newidfobject( "ELECTRICEQUIPMENT" ) #everytime you do that you add a new empty material idf1.newidfobject( "LIGHTS") #everytime you do that you add a new empty material idf1.newidfobject( "ZONEINFILTRATION:DESIGNFLOWRATE" ) #everytime you do that you add a new empty material idf1.newidfobject('ZONEVENTILATION:DESIGNFLOWRATE') # pop the object out with a given name so that we will be able to assign specific values for each: people = idf1.idfobjects['PEOPLE'][zoneindex] lights = idf1.idfobjects['LIGHTS'][zoneindex] elecequip = idf1.idfobjects['ELECTRICEQUIPMENT'][zoneindex] zoneinfildfr = idf1.idfobjects['ZONEINFILTRATION:DESIGNFLOWRATE'][ zoneindex] zoneventdfr = idf1.idfobjects['ZONEVENTILATION:DESIGNFLOWRATE'][ zoneindex] # people: people[people.fieldnames[1]] = zonename + "occupancy" #name people[people.fieldnames[2]] = zonename # Zone or ZoneList Name" people[people.fieldnames[3]] = schoccu people[people.fieldnames[4]] = "People/Area" people[ people.fieldnames[6]] = occupancy #People per Zone Floor Area people[people.fieldnames[8]] = latent # Fraction Radiant people[people. fieldnames[9]] = "autocalculate" # sensible heat fraction people[people.fieldnames[ 10]] = zonetype + "activity" # activity level schedule name # zone infiltration rate: zoneinfildfr[ zoneinfildfr.fieldnames[1]] = zonename + "infiltration" zoneinfildfr[ zoneinfildfr.fieldnames[2]] = zonename # Zone or ZoneList Name zoneinfildfr[ zoneinfildfr.fieldnames[3]] = "INFIL_SCH" # Schedule Name zoneinfildfr[zoneinfildfr.fieldnames[ 4]] = "AirChanges/Hour" #Design Flow Rate Calculation Method zoneinfildfr[ zoneinfildfr.fieldnames[8]] = 0.3 # Air Changes per Hour # lights: lights.Name = zonename + "light" lights.Zone_or_ZoneList_Name = zonename lights.Schedule_Name = schlight lights.Design_Level_Calculation_Method = "Watts/Area" lights.Watts_per_Zone_Floor_Area = lighting lights.Fraction_Radiant = 0.42 lights.Fraction_Visible = 0.18 # elecequip: elecequip.Name = zonename + "equip" elecequip.Zone_or_ZoneList_Name = zonename elecequip.Schedule_Name = schequip elecequip.Design_Level_Calculation_Method = "Watts/Area" elecequip.Watts_per_Zone_Floor_Area = equip elecequip.Fraction_Latent = 0 elecequip.Fraction_Radiant = 0.5 # VENETILATION DESIGN FLOW RATE zoneventdfr.Name = zonename + "ventilation" zoneventdfr.Zone_or_ZoneList_Name = zonename zoneventdfr.Schedule_Name = schventilation zoneventdfr.Design_Flow_Rate_Calculation_Method = "Flow/Person" zoneventdfr.Flow_Rate_per_Person = ventilationrate create_sizing_hvac_objects( idf1, zone) # inputs objects for zone sizing and boiling properties, # defined in the function create_sizing_objects # Water use equipment ........................... WUE = idf1.newidfobject("WATERUSE:EQUIPMENT") WUE.Name = zonename + "DHW" WUE.EndUse_Subcategory = "DHW_default" WUE.Peak_Flow_Rate = zone.waterflow WUE.Flow_Rate_Fraction_Schedule_Name = schoccu WUE.Target_Temperature_Schedule_Name = "SHW_default Temp Sched" WUE.Hot_Water_Supply_Temperature_Schedule_Name = "Hot Supply Temp Sched" WUE.Zone_Name = zonename # .......................... SCHEDULES FOR EQUIPMENT, LIGHTING, VENTILATION ---------------------- # Create a for loop to populate schedules for ventilation, heat and equipment. You can change the schedule using the csv file # called scheduletimes_on schedules_all = idf1.idfobjects['SCHEDULE:COMPACT'] for sch_index, schtype in Equipment_sch.iterrows(): create_simple_schedule(idf1, schedules_all, schtype, "Fraction") for sch_index, schtype in Heat_sch.iterrows(): create_simple_schedule(idf1, schedules_all, schtype, "Temperature") if versionIDF == "v860": for sch_index, schtype in Ventilation_sch.iterrows(): create_simple_schedule(idf1, schedules_all, schtype, "Fraction") # .......................... THERMOSTAT FOR HEATING ---------------------- # This for loop creates a Thermostat set point for each Type of Zone (but must not iterate through each zone) for roomindex, hg in heatgains.iterrows(): HVACTemp_Thermo = idf1.newidfobject("HVACTEMPLATE:THERMOSTAT") HVACTemp_Thermo.Name = hg.zonetype + "_Thermostat" HVACTemp_Thermo.Heating_Setpoint_Schedule_Name = hg.heatSchl HVACTemp_Thermo.Cooling_Setpoint_Schedule_Name = "Cooling Setpoint Schedule" # hg.ventilationSchl # Add to csv file the run number print("run=", run.number) # Create a new folder for the date so that they can be saved in a clean way now = datetime.datetime.now() newpath = r"C:/Users/mkj32/Documents/2016-2019 PhD/School Theoretical/Code/" + now.strftime( '%Y%m%d') if not os.path.exists(newpath): os.mkdir(newpath) os.chdir(newpath) filename = str(now)[:10] + "_school_run_%d.idf" % run.number idf1.saveas(filename) print(filename)
def generate_idf3(save_path, idf_data, idf_surfaces, idf_fenestration, wall_type, window_type, save_as): mater = 'Material' # All glazi = 'WindowMaterial:SimpleGlazingSystem' # All const = 'Construction' # All surfa = 'BuildingSurface:Detailed' # For geometry fenes = 'FenestrationSurface:Detailed' # For geometry gen00 = 'Version' # All gen01 = 'SimulationControl' # All gen02 = 'RunPeriod' # All gen03 = 'Building' # All gen04 = 'Timestep' # All gen05 = 'SizingPeriod:WeatherFileDays' # All gen06 = 'RunPeriodControl:DaylightSavingTime' # All gen07 = 'Site:GroundTemperature:BuildingSurface' # All gen08 = 'GlobalGeometryRules' # All zon01 = 'ZoneVentilation:DesignFlowRate' # For geometry zon02 = 'ZoneInfiltration:DesignFlowRate' # For geometry zon03 = 'ZoneList' # For geometry zon04 = 'Zone' # For geometry lds01 = 'People' # For geometry lds02 = 'Lights' # For geometry lds03 = 'ElectricEquipment' # For geometry sch01 = 'Schedule:Compact' sch02 = 'ScheduleTypeLimits' sch03 = 'Schedule:Day:Interval' sch04 = 'Schedule:Week:Daily' sch05 = 'Schedule:Year' sch06 = 'Schedule:Constant' hvc01 = 'HVACTemplate:Thermostat' # All hvc02 = 'HVACTemplate:Zone:VAV' # For geometry hvc03 = 'HVACTemplate:System:PackagedVAV' # All out01 = 'Output:Surfaces:Drawing' out02 = 'OutputControl:Table:Style' out03 = 'Output:Table:SummaryReports' del_01 = 'LifeCycleCost:Parameters' del_02 = 'LifeCycleCost:UsePriceEscalation' del_03 = 'ZoneControl:Thermostat' del_04 = 'ThermostatSetpoint:DualSetpoint' del_05 = 'HVACTemplate:Zone:IdealLoadsAirSystem' del_06 = 'DesignSpecification:OutdoorAir' del_07 = 'Sizing:Parameters' del_08 = 'Material:AirGap' del_09 = 'WindowMaterial:Blind' del_10 = 'WindowMaterial:Glazing' del_11 = 'WindowProperty:FrameAndDivider' del_12 = 'WindowProperty:ShadingControl' del_13 = 'Site:Location' del_14 = 'Output:VariableDictionary' del_15 = 'Output:SQLite' del_16 = 'LifeCycleCost:NonrecurringCost' # Assignments gen00 = idf_data.idfobjects[gen00.upper()][0] gen01 = idf_data.idfobjects[gen01.upper()][0] gen02 = idf_data.idfobjects[gen02.upper()][0] gen03 = idf_data.idfobjects[gen03.upper()][0] gen04 = idf_data.idfobjects[gen04.upper()][0] gen05 = idf_data.idfobjects[gen05.upper()][0] gen06 = idf_data.idfobjects[gen06.upper()][0] gen07 = idf_data.idfobjects[gen07.upper()][0] gen08 = idf_data.idfobjects[gen08.upper()][0] zon01 = idf_surfaces.idfobjects[zon01.upper()][0] zon02 = idf_surfaces.idfobjects[zon02.upper()][0] zon03 = idf_surfaces.idfobjects[zon03.upper()][0] zon04 = idf_surfaces.idfobjects[zon04.upper()] lds01 = idf_surfaces.idfobjects[lds01.upper()][0] lds02 = idf_surfaces.idfobjects[lds02.upper()][0] lds03 = idf_surfaces.idfobjects[lds03.upper()][0] sch01 = idf_data.idfobjects[sch01.upper()] sch02 = idf_data.idfobjects[sch02.upper()] sch03 = idf_data.idfobjects[sch03.upper()] sch04 = idf_data.idfobjects[sch04.upper()] sch05 = idf_data.idfobjects[sch05.upper()] sch06 = idf_data.idfobjects[sch06.upper()] hvc01 = idf_data.idfobjects[hvc01.upper()][0] hvc02 = idf_surfaces.idfobjects[hvc02.upper()] hvc03 = idf_data.idfobjects[hvc03.upper()][0] out01 = idf_data.idfobjects[out01.upper()][0] out02 = idf_data.idfobjects[out02.upper()][0] out03 = idf_data.idfobjects[out03.upper()][0] # MATERIALS mater = idf_data.idfobjects[mater.upper()] glazi = idf_data.idfobjects[glazi.upper()] # CONSTRUCTION const = idf_data.idfobjects[const.upper()] # GEOMETRY surface_objects = idf_surfaces.idfobjects[surfa.upper()] fenestration_objects = idf_fenestration.idfobjects[fenes.upper()] # CREATE NEW IDF FILE # with common info and specific geometry idf2 = IDF() idf2.new() # copy over relevant info from source idfs # GENERAL idf2.copyidfobject(gen00) idf2.copyidfobject(gen01) idf2.copyidfobject(gen02) idf2.copyidfobject(gen03) idf2.copyidfobject(gen04) idf2.copyidfobject(gen05) idf2.copyidfobject(gen06) idf2.copyidfobject(gen07) idf2.copyidfobject(gen08) # ZONE idf2.copyidfobject(zon01) idf2.copyidfobject(zon02) idf2.copyidfobject(zon03) # idf2.copyidfobject(zon04) # LOADS idf2.copyidfobject(lds01) idf2.copyidfobject(lds02) idf2.copyidfobject(lds03) # HVAC idf2.copyidfobject(hvc01) # idf2.copyidfobject(hvc02) idf2.copyidfobject(hvc03) # OUTPUT idf2.copyidfobject(out01) idf2.copyidfobject(out02) idf2.copyidfobject(out03) # SCHEDULES for i in sch01: idf2.copyidfobject(i) for i in sch02: idf2.copyidfobject(i) for i in sch03: idf2.copyidfobject(i) for i in sch04: idf2.copyidfobject(i) for i in sch05: idf2.copyidfobject(i) for i in sch06: idf2.copyidfobject(i) for i in zon04: idf2.copyidfobject(i) for i in hvc02: idf2.copyidfobject(i) # MATERIALS for i in mater: idf2.copyidfobject(i) # GLAZING for i in glazi: idf2.copyidfobject(i) # CONSTRUCTIONS for i in const: idf2.copyidfobject(i) # Basic setup done # Now I need geometry from a specific file. # GEOMETRY for i in surface_objects: idf2.copyidfobject(i) for i in fenestration_objects: idf2.copyidfobject(i) new_surface = idf2.idfobjects[surfa.upper()] new_subsurface = idf2.idfobjects[fenes.upper()] # Now I want to change the construction of each surface and glazing. floor_type = 'Slab A' ceiling_type = 'Slab A' roof_type = 'Roof A' for surface in new_surface: if surface['Surface_Type'] == 'Floor': surface.Construction_Name = floor_type for surface in new_surface: if surface['Surface_Type'] == 'Ceiling': surface.Construction_Name = ceiling_type for surface in new_surface: if surface['Surface_Type'] == 'Roof': surface.Construction_Name = roof_type for surface in new_surface: if surface['Surface_Type'] == 'Wall': surface.Construction_Name = wall_type for subsurface in new_subsurface: if subsurface['Surface_Type'] == 'Window': subsurface.Construction_Name = window_type # Save it to the disk. idf2.saveas('{}/{}.idf'.format(save_path, save_as)) idf_file = '{}/{}.idf'.format(save_path, save_as) return idf_file
from eppy import hvacbuilder from io import StringIO iddfile = "../eppy/resources/iddfiles/Energy+V7_0_0_036.idd" IDF.setiddname(iddfile) # <codecell> # make the topology of the loop idf = IDF(StringIO("")) # makes an empty idf file in memory with no file name loopname = "p_loop" sloop = ["sb0", ["sb1", "sb2", "sb3"], "sb4"] # supply side of the loop dloop = ["db0", ["db1", "db2", "db3"], "db4"] # demand side of the loop hvacbuilder.makeplantloop(idf, loopname, sloop, dloop) idf.saveas("hhh1.idf") # <markdowncell> # We have made plant loop and saved it as hhh1.idf. # Now let us look at what the loop looks like. # <headingcell level=3> # Diagram of the loop # <markdowncell> # Let us use the script "eppy/useful_scripts/loopdiagrams.py" to draw this diagram # <markdowncell>
def datafield(yc_keys, xc_keys): iddfile = "./Energy+9.1.idd" IDF.setiddname(iddfile) idfname = "./RefBldgLargeOfficeNew2004_Chicago.idf" idf = IDF(idfname) # change the output variable and meter # output_frequency='Daily' output_frequency = 'Monthly' variable = [] for i in range(len(xc_keys)): variable1 = idf.newidfobject("Output:Variable".upper()) variable1.Key_Value = '*' variable1.Variable_Name = xc_keys[i] variable1.Reporting_Frequency = output_frequency variable.append(variable1) idf.idfobjects['Output:Variable'.upper()] = variable meter = [] for i in range(len(yc_keys)): meter1 = idf.newidfobject("Output:Meter".upper()) meter1.Key_Name = yc_keys[i] meter1.Reporting_Frequency = output_frequency meter.append(meter1) idf.idfobjects['Output:Meter'.upper()] = meter idf.idfobjects['RUNPERIOD'][0].Begin_Month = 1 idf.idfobjects['RUNPERIOD'][0].Begin_Day_of_Month = 1 idf.idfobjects['RUNPERIOD'][0].End_Month = 12 idf.idfobjects['RUNPERIOD'][0].End_Day_of_Month = 31 idf.saveas('C:/Users/songc/Desktop/work file/Updated_Model.idf') idfname1 = 'C:/Users/songc/Desktop/work file/Updated_Model.idf' # This IDF file is updated at each iteration. epwfile = './SPtMasterTable_52384_2011_amy.epw' subprocess.call([ 'C:/EnergyPlusV9-1-0/energyplus.exe', '-d', "C:/Users/songc/Desktop/work file/result_folder", '-w', epwfile, idfname1 ]) eso_file = './result_folder/eplusout.eso' [ycoutput, xcoutput] = comp_data_reader(eso_file, yc_keys, xc_keys) yc_df1 = pd.DataFrame(ycoutput, index=yc_keys).T xc_df1 = pd.DataFrame(xcoutput, index=xc_keys).T epwfile2 = './SPtMasterTable_52384_2012_amy.epw' subprocess.call([ 'C:/EnergyPlusV9-1-0/energyplus.exe', '-d', "C:/Users/songc/Desktop/work file/result_folder", '-w', epwfile2, idfname1 ]) eso_file = './result_folder/eplusout.eso' [ycoutput, xcoutput] = comp_data_reader(eso_file, yc_keys, xc_keys) yc_df2 = pd.DataFrame(ycoutput, index=yc_keys).T xc_df2 = pd.DataFrame(xcoutput, index=xc_keys).T yc_df = pd.concat([yc_df1, yc_df2], axis=0) xc_df = pd.concat([xc_df1, xc_df2], axis=0) df = pd.concat([yc_df, xc_df], axis=1) df.to_csv('DATAFIELD_Multi.csv', index=False) df_single = pd.concat([yc_df.iloc[:, 0], xc_df], axis=1) df_single.to_csv('DATAFIELD_Single.csv', index=False)
CSVDir = DirName+'/runtrial/WeatherFileNameList.csv' WriteEPWNameToCSV(epwDir, CSVDir , 8) weatherfilename_list = ReadFileNameInCsv(CSVDir) print(weatherfilename_list) ##run with different locations for i in weatherfilename_list: epwname = epwDir + i +'.epw' ##Before write the path, put weather files in EnergyPlus WeatherData folder ddyname = ddyDir + i +'.ddy' fname1 = DirName + '/runtrial/TrialKA2_Unsized.idf' idf1 = IDF(fname1, epwname) UpdateLocationInfinIDF(idf1,ddyname) ##idf1.printidf() building = idf1.idfobjects['BUILDING'][0] building.Name = "KA2 A Flatroof Sample Building" objectlist = idf1.idfobjects rundirname = u'../eppy_energy-/runtrial/' resultsdir = rundirname+'results'+i ##os.makedirs(resultsdir) idf1.saveas(DirName + "/idfs/"+i+'.idf') idf1.run(output_directory = resultsdir) Axis = 0 while Axis in range(0,360): building.North_Axis = Axis ##idf1.saveas(DirName+'/idfs/Axises/'+str(Axis)+".idf") resultsdirAxis= rundirname+'results'+i+'Axis'+str(Axis) ##os.makedirs(resultsdirAxis) ##idf1.run(output_directory = resultsdirAxis) Axis += 45
def modify_IDF_global(input_file_path, iddfile, nbiterations, sa_fname, nbbatches, start_month, end_month, m_file1, m_file2, monthprefix): """creates idf based on baseline IDF, and three inputs: file path to baseline IDF, pathname to EnergyPlus Package, and nb of iterations to run the simulation i.e. number of simulations based on the sensitivity analysis input file.""" # Prepare the idd file and file paths IDF.setiddname(iddfile) os.chdir(input_file_path) # Name baseline IDF file baselineIDF = input_file_path + r'/CosimulationFiles/GlobalSA_BaselineIDF_Cosim.idf' # Load all the input files sa_inputs = pd.read_csv(sa_fname) #Planted_area # maybe used to modify size on internal mass? # # now we divide into 4 batches #nbiterations=100 #nbbatches=4 nbiterations_inbatch = int(nbiterations / nbbatches) #letters_batch =('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J') letters_batch = list(itertools.islice(excel_cols(), nbbatches)) batch_index = range(0, int(nbiterations_inbatch)) for batch in range(0, nbbatches): print("-----------------Batch number is now", batch) for runindex in batch_index: print("Index number is now", runindex) runindex = runindex + nbiterations_inbatch * batch print("******Index number is now", runindex) # Now we can select the correct row from sa_inputs run = sa_inputs.iloc[int(runindex), ] # for runindex, run in sa_inputs.head(n=nbiterations).iterrows(): # only run for the first iteration print(runindex, run) idf1 = IDF(baselineIDF) # modify run period mofify_run_period(idf1, from_day=1, from_month=start_month, to_day=31, to_month=end_month) ## Heating and cooling setpoints of the greenhouse ============================================= #Cooling_SP_GH #Heating_SP_GH # modify the scheduled cooling and heating setpoints, objects 72 and 73 respectively heatingsched = idf1.idfobjects["SCHEDULE:COMPACT"][51 - 1] coolingsched = idf1.idfobjects["SCHEDULE:COMPACT"][52 - 1] # nightheating for night_fieldname in [6, 10, 13, 17, 20]: #print(night_fieldname) heatingsched[heatingsched.fieldnames[night_fieldname]] = round( run.Heating_SP_GH * 0.9, 1) #it can get 10% colder at night coolingsched[coolingsched.fieldnames[night_fieldname]] = round( run.Cooling_SP_GH * 1.1, 1) #it can get 10% warmer at night for day_fieldname in [8, 15]: heatingsched[heatingsched.fieldnames[day_fieldname]] = round( run.Heating_SP_GH, 1) #it can get 10% colder at night coolingsched[coolingsched.fieldnames[day_fieldname]] = round( run.Cooling_SP_GH, 1) #it can get 10% warmer at night #shading ======================================================= #rooftop_window ## ..........................SHADING..................................................... solar_transmittance = round(run.shading, 2) solar_reflectance = 0.99 - solar_transmittance # only one shading control to add: # to view the field names use shade.fieldnames shade = idf1.idfobjects["WINDOWMATERIAL:SHADE"][0] shade.Solar_Transmittance = solar_transmittance shade.Solar_Reflectance = solar_reflectance shade.Visible_Transmittance = solar_transmittance shade.Visible_Reflectance = solar_reflectance ## ..........................ROOFTOP WINDOW..................................................... windowsize = round(run.rooftop_window, 2) # percentage of rooftop size # max_x = 74.15 max_y = -34.44 min_x = 38.15 min_y = -41.44 new_min_x = min_x + (36 - sqrt(windowsize) * 36) / 2 new_min_y = min_y + (7 - sqrt(windowsize) * 7) / 2 new_max_x = new_min_x + 36 * sqrt(windowsize) new_max_y = new_min_y + 7 * sqrt(windowsize) # verification: (new_max_x-new_min_x)*(new_max_y-new_min_y)-252*windowsize # create window object # count how many windows there are nbwindows = len(idf1.idfobjects["FENESTRATIONSURFACE:DETAILED"]) ghwindow = idf1.idfobjects["FENESTRATIONSURFACE:DETAILED"][ nbwindows - 1] # select the last window # identify the fieldnames of the window object #ghwindow.fieldnames # modify the coordinates ghwindow.Vertex_1_Xcoordinate = new_min_x ghwindow.Vertex_1_Ycoordinate = new_max_y ghwindow.Vertex_2_Xcoordinate = new_min_x ghwindow.Vertex_2_Ycoordinate = new_min_y ghwindow.Vertex_3_Xcoordinate = new_max_x ghwindow.Vertex_3_Ycoordinate = new_min_y ghwindow.Vertex_4_Xcoordinate = new_max_x ghwindow.Vertex_4_Ycoordinate = new_max_y #ratio_airmix_GH #ratio_airmix_CR ## AIR MIXING GREENHOUSE ========================================= zonemixing = idf1.idfobjects["ZONEMIXING"] # Greenhouse ventilation rate: ach_GH = round(run.ACH_GH, 2) # total ventilation rate # the ratio of mixing is run.ratio_airmix_GH zonemixing[0].Air_Changes_per_Hour = ach_GH * run.ratio_airmix_GH ghventilation = idf1.idfobjects["ZONEVENTILATION:DESIGNFLOWRATE"][ 6] ghventilation.Air_Changes_per_Hour = ach_GH * (1 - run.ratio_airmix_GH) # AIR MIXING CLASSROOM ------------------------------------- ACH_CR = round(run.ACH_CR, 2) # total ventilation rate # the ratio of mixing is run.ratio_airmix_CR zonemixing[1].Air_Changes_per_Hour = ACH_CR * run.ratio_airmix_CR crventilation = idf1.idfobjects["ZONEVENTILATION:DESIGNFLOWRATE"][ 8] crventilation.Air_Changes_per_Hour = ACH_CR * (1 - run.ratio_airmix_CR) ## CREATE THE IDF FILE =========================== # Add to csv file the run number print("run=", runindex) # Create a new folder for the date so that they can be saved in a clean way now = datetime.datetime.now() # monthprefix = "Jan" newpath = input_file_path + "/" + now.strftime( '%Y%m%d') + "_" + monthprefix + "_Batch" + letters_batch[batch] if not os.path.exists(newpath): os.mkdir(newpath) variables_file_path = input_file_path + "/CosimulationFiles/variables.cfg" shutil.copy(variables_file_path, newpath) cosim_file_path1 = input_file_path + "/CosimulationFiles/" + m_file1 cosim_file_path2 = input_file_path + "/CosimulationFiles/" + m_file2 cosim_new_file_path1 = newpath + "/Run_Cosim_" + monthprefix + "_Batch_" + letters_batch[ batch] + "_C1.m" cosim_new_file_path2 = newpath + "/Run_Cosim_" + monthprefix + "_Batch_" + letters_batch[ batch] + "_C2.m" shutil.copy(cosim_file_path1, cosim_new_file_path1) shutil.copy(cosim_file_path2, cosim_new_file_path2) os.chdir(newpath) filename = str(now)[:10] + "_SA_run_%d.idf" % runindex idf1.saveas(filename) print(filename)
def create_combined_idf_archetype(save_folder_path, idflist=list): """ Combines all materials, constructions stored in different idfs and merges them into a single idf file Run Order: 1)Gathers all material and construction objects into lists stored in idfs 2)Selects the base IDF and deletes all construction and material objects 3)Creates new materials and constructions from the lists created in 1. 4)Redefines output variables in a way that BuildME accepts 5)Saves a new idf file, ready to be used with BuildME :param save_folder_path: save folder, where the new merged IDF will be saved :param idflist: idf list containing the idf files to be merged this list should only contain an archetype type at a time (e.g. only SFH) :return: a new merged archetype idf for BuildME """ cons_list = [] mat_list = [] matnomass_list = [] matwin_list = [] ffloor_list = [] cwall_list = [] merged_idf = "" # Gets required objects in all idf files and puts in a list for idf in idflist: fhandle = StringIO(idf) idf = IDF(fhandle) for cons in idf.idfobjects["Construction".upper()]: cons_list.append(cons) for mat in idf.idfobjects["Material".upper()]: mat_list.append(mat) for matnomass in idf.idfobjects["Material:NoMass".upper()]: matnomass_list.append(matnomass) for matwin in idf.idfobjects[ "WindowMaterial:SimpleGlazingSystem".upper()]: matwin_list.append(matwin) for ffloor in idf.idfobjects[ "Construction:FfactorGroundFloor".upper()]: ffloor_list.append(ffloor) for cwall in idf.idfobjects[ "Construction:CfactorUndergroundWall".upper()]: cwall_list.append(cwall) # Removes duplicate elements cons_list = reduce(lambda l, x: l.append(x) or l if x not in l else l, cons_list, []) mat_list = reduce(lambda l, x: l.append(x) or l if x not in l else l, mat_list, []) matnomass_list = reduce(lambda l, x: l.append(x) or l if x not in l else l, matnomass_list, []) matwin_list = reduce(lambda l, x: l.append(x) or l if x not in l else l, matwin_list, []) ffloor_list = reduce(lambda l, x: l.append(x) or l if x not in l else l, ffloor_list, []) cwall_list = reduce(lambda l, x: l.append(x) or l if x not in l else l, cwall_list, []) newobjects = cons_list + matnomass_list + matwin_list + ffloor_list + mat_list + cwall_list reduced_newobjects = reduce( lambda l, x: l.append(x) or l if x not in l else l, newobjects, []) # Selects the base IDF, deletes all of the objects and rewrites new objects from other IDFs for idf in idflist: fhandle = StringIO(idf) idf = IDF(fhandle) print( f'Now, {idf.idfobjects["Building".upper()][0].Name} values are being written to the merged IDF...' ) if "BASE" in idf.idfobjects["Building".upper()][0].Name: idf.removeallidfobjects("CONSTRUCTION") idf.removeallidfobjects("MATERIAL") idf.removeallidfobjects("MATERIAL:NOMASS") idf.removeallidfobjects("WINDOWMATERIAL:SIMPLEGLAZINGSYSTEM") idf.removeallidfobjects("CONSTRUCTION:FFACTORGROUNDFLOOR") idf.removeallidfobjects("CONSTRUCTION:CFACTORUNDERGROUNDWALL") # Output Variables needs to be redefined for BuildME idf.removeallidfobjects("OUTPUT:VARIABLEDICTIONARY") idf.removeallidfobjects("OUTPUT:SURFACES:DRAWING") idf.removeallidfobjects("OUTPUT:CONSTRUCTIONS") idf.removeallidfobjects("OUTPUT:TABLE:SUMMARYREPORTS") idf.removeallidfobjects("OUTPUT:TABLE:MONTHLY") idf.removeallidfobjects("OUTPUTCONTROL:TABLE:STYLE") idf.removeallidfobjects("OUTPUT:VARIABLE") idf.removeallidfobjects("OUTPUT:METER") print("Output Variables are being changed...") # New output variables are defined by using existing SFH archetype located in data/archetype folder SFH_IDF = IDF("..//data//archetype//USA//SFH.idf") outputlist = [] objlist = [ "OUTPUT:METER", "OUTPUT:VARIABLEDICTIONARY", "OUTPUT:SURFACES:DRAWING", "OUTPUT:CONSTRUCTIONS", "OUTPUT:TABLE:SUMMARYREPORTS", "OUTPUT:TABLE:MONTHLY", "OUTPUTCONTROL:TABLE:STYLE", "OUTPUT:VARIABLE" ] for obj in objlist: if obj in [x for x in SFH_IDF.idfobjects]: for item in SFH_IDF.idfobjects[f"{obj}"]: outputlist.append(item) for newobj in outputlist: idf.copyidfobject(newobj) # Checks if there are still duplicates seen = set() dupes = [] for x in reduced_newobjects: if x.Name in seen: dupes.append(x.Name) else: seen.add(x.Name) idf.copyidfobject(x) # Renames the merged IDF building = idf.idfobjects["Building".upper()][0].Name building = building.split("-")[0] idf.idfobjects["Building".upper()][0].Name = building building = building.split("BASE")[1] idf.saveas(f"{save_folder_path}/{building}-BuildME.idf") merged_idf = idf print("The new merged idf file is successfully created") return merged_idf
from eppy import modeleditor from eppy.modeleditor import IDF from eppy import bunch_subclass def autosize_fieldname(idfobject): """return autsizeable field names in idfobject""" # undocumented stuff in this code return [ fname for (fname, dct) in zip(idfobject.objls, idfobject["objidd"]) if "autosizable" in dct ] iddfile = "../resources/iddfiles/Energy+V8_0_0.idd" fname1 = "../resources/idffiles/V8_0_0/5ZoneWaterLoopHeatPump.idf" IDF.setiddname(iddfile) idf = IDF(fname1) idf.saveas("./a.idf") allidfobjects = idf.idfobjects for objname in list(allidfobjects.keys()): idfobjects = allidfobjects[objname] for idfobject in idfobjects: autofields = autosize_fieldname(idfobject) for autofield in autofields: idfobject[autofield] = "autosize" idf.saveas("./b.idf")
from eppy.modeleditor import IDF from eppy import hvacbuilder from StringIO import StringIO iddfile = "../eppy/resources/iddfiles/Energy+V7_0_0_036.idd" IDF.setiddname(iddfile) # <codecell> # make the topology of the loop idf = IDF(StringIO('')) # makes an empty idf file in memory with no file name loopname = "p_loop" sloop = ['sb0', ['sb1', 'sb2', 'sb3'], 'sb4'] # supply side of the loop dloop = ['db0', ['db1', 'db2', 'db3'], 'db4'] # demand side of the loop hvacbuilder.makeplantloop(idf, loopname, sloop, dloop) idf.saveas("hhh1.idf") # <markdowncell> # We have made plant loop and saved it as hhh1.idf. # Now let us look at what the loop looks like. # <headingcell level=3> # Diagram of the loop # <markdowncell> # Let us use the script "eppy/useful_scripts/loopdiagrams.py" to draw this diagram # <markdowncell>
from eppy import modeleditor from eppy.modeleditor import IDF from eppy import bunch_subclass def autosize_fieldname(idfobject): """return autsizeable field names in idfobject""" # undocumented stuff in this code return [fname for (fname, dct) in zip(idfobject.objls, idfobject['objidd']) if 'autosizable' in dct] iddfile = "../resources/iddfiles/Energy+V8_0_0.idd" fname1 = "../resources/idffiles/V8_0_0/5ZoneWaterLoopHeatPump.idf" IDF.setiddname(iddfile) idf = IDF(fname1) idf.saveas("./a.idf") allidfobjects = idf.idfobjects for objname in list(allidfobjects.keys()): idfobjects = allidfobjects[objname] for idfobject in idfobjects: autofields = autosize_fieldname(idfobject) for autofield in autofields: idfobject[autofield] = "autosize" idf.saveas("./b.idf")
Idx = 0 for i in range(0,len(BatchProcessing)): # Display the progress of the script if Idx >= 2: print "Creating "+str(Idx-1)+" out of "+str(len(BatchProcessing)-2)+" models." # Initialization #2 NbRows = BatchProcessing[i] if NbRows[0] <> 'idf' and NbRows[0] <> '-': # Initialization #3 idf_file = IDF(NbRows[0]) # Iterates throught the CSV file and execute the specified functions for j in range(2,len(NbRows)): # Retrieve the user input arguments arguments = NbRows[j].split(",") #print str(len(arguments))+" " +str(arguments[0]) # If not argument is specified do not execute the function if not(len(arguments) == 1 and arguments[0] == "-"): item = BatchProcessing[0][j] func = getattr(eval(item),item) func(idf_file, arguments) # Save the modified IDF file idf_file.saveas(NbRows[1][:-4]+".idf") Idx = Idx + 1 print "Done."