def test_building_geometry(ureg, res_folder): expected_file_path = os.path.dirname(__file__) / Path("./expected_results/idf_expected_geometry.idf") site_vertices_file = os.path.dirname(__file__) / Path("./testfixture/SiteVertices.csv") main_bldg_fid = 2 glazing_ratio = 0.16 infiltration_rate = 0.71 * ureg.ACH flat_vertices = cesarp.geometry.csv_input_parser.read_sitevertices_from_csv(site_vertices_file, __sitevertices_labels) site_bldgs = vertices_basics.convert_flat_site_vertices_to_per_bldg_footprint(flat_vertices) bldg_geometry = GeometryBuilder(main_bldg_fid, site_bldgs, glazing_ratio) bldg_shape = bldg_geometry.get_bldg_shape_detailed() idf_file_path = res_folder / Path("idf_geometry.idf") aux_files_handler = RelativeAuxiliaryFilesHandler() aux_files_handler.set_destination(res_folder, "profiles") my_idf_writer = CesarIDFWriter(idf_file_path, ureg, aux_files_handler) bldg_constr = __get_constr_for(main_bldg_fid, 1930, ureg) bldg_constr.infiltration_rate = infiltration_rate # overwrite because the default has higher precision than what was written with the matlab version idf = IDF(str(idf_file_path)) my_idf_writer.add_building_geometry(idf, bldg_shape, ConstructionIDFWritingHandler(bldg_constr, None, ureg)) idf.save() assert are_files_equal(idf_file_path, expected_file_path, ignore_line_nrs=[1]) # test wrong infiltration rate unit bldg_constr.infiltration_rate = 3 * ureg.m ** 3 / ureg.sec with pytest.raises(Exception): my_idf_writer.add_building_geometry(idf, bldg_shape, ConstructionIDFWritingHandler(bldg_constr, None, ureg))
def test_save_copy(self): """Test savecopy with a new filename. IDF.savecopy(fname) doesn't change the filename. The next save should save with the original name. Fails if on a following save, the copy is changed. """ idf = IDF(self.startfile) idf.savecopy(self.copyfile) setversion(idf, "7.5") idf.save() idf2 = IDF(self.copyfile) result = getversion(idf2) expected = "7.3" # unchanged since version was changed after savecopy assert result == expected idf3 = IDF(self.startfile) result = getversion(idf3) expected = "7.5" # should be changed in the original file assert result == expected
def test_save_copy(self): """Test savecopy with a new filename. IDF.savecopy(fname) doesn't change the filename. The next save should save with the original name. Fails if on a following save, the copy is changed. """ idf = IDF(self.startfile) idf.savecopy(self.copyfile) setversion(idf, '7.5') idf.save() idf2 = IDF(self.copyfile) result = getversion(idf2) expected = '7.3' # unchanged since version was changed after savecopy assert result == expected idf3 = IDF(self.startfile) result = getversion(idf3) expected = '7.5' # should be changed in the original file assert result == expected
def auto_generate_from_template(cop, number, base_idf_dir, final_idf_dir, idd_file_dir): IDF.setiddname(idd_file_dir) idf = IDF(base_idf_dir) idf.idfobjects['ChillerHeaterPerformance:Electric:EIR'][ 0].Reference_Cooling_Mode_COP = cop idf.idfobjects['CentralHeatPumpSystem'][ 0].Number_of_Chiller_Heater_Modules_1 = number idf.save(final_idf_dir)
def auto_generate_from_template(peak_heating_w, peak_cooling_w, heating_cop, cooling_cop, n_borehole, soil_k, base_idf_dir, final_idf_dir, idd_file_dir): IDF.setiddname(idd_file_dir) idf = IDF(base_idf_dir) idf = auto_update_LP_flow_rates(idf, peak_heating_w, peak_cooling_w) idf = auto_update_ghex_system(idf, peak_heating_w, peak_cooling_w, heating_cop, cooling_cop, n_borehole, soil_k) idf.save(final_idf_dir)
def test_simulations_basic_settings(ureg, res_folder): expected_file_path = os.path.dirname(__file__) / Path( "./expected_results/idf_expected_simulation_basics.idf") os.makedirs(res_folder, exist_ok=True) aux_files_handler = RelativeAuxiliaryFilesHandler() aux_files_handler.set_destination(res_folder, "profiles") idf_file_path = res_folder / Path("idf_simulation_basics.idf") my_idf_writer = CesarIDFWriter(idf_file_path, ureg, aux_files_handler) idf = IDF(str(idf_file_path)) my_idf_writer.add_basic_simulation_settings(idf, SiteGroundTemperatureFactory(ureg).get_ground_temperatures()) idf.save() assert are_files_equal(idf_file_path, expected_file_path, ignore_line_nrs=[1]) == True
def test_save(): """ Test the IDF.save() function using a filehandle to avoid external effects. """ file_text = "Material,TestMaterial, !- Name" idf = IDF(StringIO(file_text)) # test save with just a filehandle file_handle = StringIO() idf.save(file_handle) expected = "TestMaterial" file_handle.seek(0) result = file_handle.read() # minimal test that TestMaterial is being written to the file handle assert expected in result
def test_save(self): """Test save with a changed version number. Fails if the version number has not been changed. """ idf = IDF(self.startfile) setversion(idf, "7.4") idf.save() idf2 = IDF(self.startfile) assert idf is not idf2 # be sure we don't just have an in-memory copy result = getversion(idf2) expected = "7.4" assert result == expected
def test_save(self): """Test save with a changed version number. Fails if the version number has not been changed. """ idf = IDF(self.startfile) setversion(idf, '7.4') idf.save() idf2 = IDF(self.startfile) assert idf is not idf2 # be sure we don't just have an in-memory copy result = getversion(idf2) expected = '7.4' assert result == expected
def test_lineendings(self): """Test lineendings are set correctly on each platform.""" idf = IDF(self.startfile) idf.save(lineendings="windows") with open(self.startfile, "rb") as sf: txt = sf.read() print(txt.count(b"\r\n")) lines = txt.splitlines() numlines = len(lines) assert numlines == txt.count(b"\r\n") + 1 # no CR on last line idf.save(lineendings="unix") with open(self.origfile, "rb") as of: txt = of.read() lines = txt.splitlines() numlines = len(lines) assert numlines == txt.count(b"\n") + 1 # no CR on last line
def test_lineendings(self): """Test lineendings are set correctly on each platform. """ idf = IDF(self.startfile) idf.save(lineendings='windows') with open(self.startfile, 'rb') as sf: txt = sf.read() print(txt.count(b'\r\n')) lines = txt.splitlines() numlines = len(lines) assert numlines == txt.count(b'\r\n') + 1 # no CR on last line idf.save(lineendings='unix') with open(self.origfile, 'rb') as of: txt = of.read() lines = txt.splitlines() numlines = len(lines) assert numlines == txt.count(b'\n') + 1 # no CR on last line
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 write_bldg_model(self, bldg_model: BuildingModel) -> None: """ :param bldg_model: Building model to write to IDF :type bldg_model: BuildingModel """ idf = IDF(str(self.idf_file_path)) self.add_basic_simulation_settings(idf, bldg_model.site.site_ground_temperatures) constr_handler = ConstructionIDFWritingHandler(bldg_model.bldg_construction, bldg_model.neighbours_construction_props, self.unit_registry) self.add_building_geometry(idf, bldg_model.bldg_shape, constr_handler) self.add_neighbours(idf, bldg_model.neighbours, constr_handler) self.add_building_properties( idf, bldg_model.bldg_operation_mapping, bldg_model.bldg_construction.installation_characteristics, bldg_model.bldg_construction.infiltration_rate, self.__handle_profile_file(bldg_model.bldg_construction.infiltration_profile), bldg_model.bldg_construction.window_constr.shade, ) idf = self.add_output_settings(idf) idf.save(filename=str(self.idf_file_path))
def test_save_with_lineendings_and_encodings(self): """ Test the IDF.save() function with combinations of encodings and line endings. """ idf = IDF(self.startfile) lineendings = ("windows", "unix", "default") encodings = ("ascii", "latin-1", "UTF-8") for le, enc in product(lineendings, encodings): idf.save(lineendings=le, encoding=enc) with open(self.startfile, "rb") as sf: result = sf.read() if le == "windows": assert b"\r\n" in result elif le == "unix": assert b"\r\n" not in result elif le == "default": assert os.linesep.encode(enc) in result
def test_save_with_lineendings_and_encodings(self): """ Test the IDF.save() function with combinations of encodings and line endings. """ idf = IDF(self.startfile) lineendings = ('windows', 'unix', 'default') encodings = ('ascii', 'latin-1', 'UTF-8') for le, enc in product(lineendings, encodings): idf.save(lineendings=le, encoding=enc) with open(self.startfile, 'rb') as sf: result = sf.read() if le == 'windows': assert b'\r\n' in result elif le == 'unix': assert b'\r\n' not in result elif le == 'default': assert os.linesep.encode(enc) in result
def test_save_with_lineendings_and_encodings(): """ Test the IDF.save() function with combinations of encodings and line endings. """ file_text = "Material,TestMaterial, !- Name" idf = IDF(StringIO(file_text)) lineendings = ('windows', 'unix', 'default') encodings = ('ascii', 'latin-1', 'UTF-8') for le, enc in product(lineendings, encodings): file_handle = StringIO() idf.save(file_handle, encoding=enc, lineendings=le) file_handle.seek(0) result = file_handle.read().encode(enc) if le == 'windows': assert b'\r\n' in result elif le == 'unix': assert b'\r\n' not in result elif le == 'default': assert os.linesep.encode(enc) in result
def test_save_with_lineendings_and_encodings(): """ Test the IDF.save() function with combinations of encodings and line endings. """ file_text = "Material,TestMaterial, !- Name" idf = IDF(StringIO(file_text)) lineendings = ("windows", "unix", "default") encodings = ("ascii", "latin-1", "UTF-8") for le, enc in product(lineendings, encodings): file_handle = StringIO() idf.save(file_handle, encoding=enc, lineendings=le) file_handle.seek(0) result = file_handle.read().encode(enc) if le == "windows": assert b"\r\n" in result elif le == "unix": assert b"\r\n" not in result elif le == "default": assert os.linesep.encode(enc) in result
def test_neighbour_shading_objects(ureg, res_folder): expected_file_path = os.path.dirname(__file__) / Path("./expected_results/idf_expected_neighbours.idf") site_vertices_file = os.path.dirname(__file__) / Path("./testfixture/SiteVertices_minimized.csv") main_bldg_fid = 2 glazing_ratio = 0.16 flat_vertices = cesarp.geometry.csv_input_parser.read_sitevertices_from_csv(site_vertices_file, __sitevertices_labels) site_bldgs = vertices_basics.convert_flat_site_vertices_to_per_bldg_footprint(flat_vertices) bldg_geometry = GeometryBuilder(main_bldg_fid, site_bldgs, glazing_ratio) neighbours = bldg_geometry.get_bldg_shape_of_neighbours() idf_file_path = res_folder / Path("idf_neighbours.idf") aux_files_handler = RelativeAuxiliaryFilesHandler() aux_files_handler.set_destination(res_folder, "profiles") my_idf_writer = CesarIDFWriter(idf_file_path, ureg, aux_files_handler) win_glass_constr = __get_constr_for(main_bldg_fid, 1930, ureg).window_constr.glass neigh_constr = __get_shading_constr(win_glass_constr, ureg) idf = IDF(str(idf_file_path)) my_idf_writer.add_neighbours(idf, neighbours, ConstructionIDFWritingHandler(None, neigh_constr, ureg)) idf.save() assert are_files_equal(idf_file_path, expected_file_path, ignore_line_nrs=[1])
def __init__(self, config): self.directory = os.path.dirname( os.path.dirname(os.path.realpath(__file__))) self.idf_name = 'eplusModel' # directory where csv of each episode are saved if 'res_directory' in config: self.res_directory = config['res_directory'] else: self.res_directory = '' print("File directory: ", self.directory) # EnergyPlus weather file if "idf_directory_name" in config: self.idf_directory_name = config["idf_directory_name"] else: self.idf_directory_name = 'StorageTank_Model' if "weather_file" in config: self.weather_file = config["weather_file"] else: self.weather_file = 'weatherFiles/ITA_TORINO-CASELLE_IGDG' # EnergyPlus TimeStep as specified in .idf file if "ep_time_step" in config: self.ep_time_step = config["ep_time_step"] else: self.ep_time_step = 12 # Number of days of a simulation as specified in the RunPeriod object of the .idf file if "simulation_days" in config: self.simulation_days = config["simulation_days"] else: self.simulation_days = 90 if "reward_multiplier" in config: self.reward_multiplier = config["reward_multiplier"] else: self.reward_multiplier = 10 # Tank properties if "tank_volume" in config: self.tank_volume = config["tank_volume"] else: self.tank_volume = 10 if "tank_heat_gain_coefficient" in config: self.tank_heat_gain_coefficient = config[ "tank_heat_gain_coefficient"] else: self.tank_heat_gain_coefficient = 12 # Minimum Temperature allowed for water in the thermal storage tank. if "tank_min_temperature" in config: self.tank_min_temperature = config["tank_min_temperature"] else: self.tank_min_temperature = 10 # Maximum Temperature allowed for water in the thermal storage tank. if "tank_max_temperature" in config: self.tank_max_temperature = config["tank_max_temperature"] else: self.tank_max_temperature = 18 if "begin_month" in config: self.begin_month = config["begin_month"] else: self.begin_month = 6 if "end_month" in config: self.end_month = config["end_month"] else: self.end_month = 8 if "begin_day_of_month" in config: self.begin_day_of_month = config["begin_day_of_month"] else: self.begin_day_of_month = 1 if "end_day_of_month" in config: self.end_day_of_month = config["end_day_of_month"] else: self.end_day_of_month = 29 if "day_shift" in config: self.day_shift = config["day_shift"] else: self.day_shift = 152 if "pv_nominal_power" in config: self.pv_nominal_power = config["pv_nominal_power"] else: self.pv_nominal_power = 1500 if "battery_size" in config: self.battery_size = config["battery_size"] else: self.battery_size = 2400 if "horizon" in config: self.horizon = config["horizon"] else: self.horizon = 24 self.price_schedule_name = config["price_schedule_name"] idd_file = 'supportFiles\\Energy+9-2-0.idd' file_name = 'EplusModels\\' + self.idf_directory_name + '\\eplusModel.idf' IDF.setiddname(idd_file) idf_file = IDF(file_name) runperiod = idf_file.idfobjects['RUNPERIOD'][0] runperiod.Begin_Month = self.begin_month runperiod.Begin_Day_of_Month = self.begin_day_of_month runperiod.End_Month = self.end_month runperiod.End_Day_of_Month = self.end_day_of_month storage_tank = idf_file.idfobjects[ 'ThermalStorage:ChilledWater:Mixed'][0] storage_tank.Tank_Volume = self.tank_volume storage_tank.Heat_Gain_Coefficient_from_Ambient_Temperature = self.tank_heat_gain_coefficient idf_file.save('eplusModels\\' + self.idf_directory_name + '\\eplusModel.idf', encoding='UTF-8') # EnergyPlus path in the local machine self.eplus_path = 'C:/EnergyPlusV9-2-0/' # Number of steps per day self.DAYSTEPS = int(24 * self.ep_time_step) # Total number of steps self.MAXSTEPS = int(self.simulation_days * self.DAYSTEPS) # Time difference between each step in seconds self.deltaT = (60 / self.ep_time_step) * 60 # Outputs given by EnergyPlus, defined in variables.cfg self.outputs = [] # Inputs expected by EnergyPlus, defined in variables.cfg self.inputs = [] # Current step of the simulation self.kStep = 0 self.hStep = 0 # Instance of EnergyPlus simulation self.ep = None # state can be all the inputs required to make a control decision # getting all the outputs coming from EnergyPlus for the time being with open(self.directory + '\\supportFiles\\state_space_variables.json') as json_file: buildings_states = json.load(json_file) with open(self.directory + '\\supportFiles\\state_rescaling_table.json') as json_file: rescaling_table = json.load(json_file) self.state_types, self.state_names, self.state_mins, self.state_maxs = \ get_state_variables(data=buildings_states, rescaling_table=rescaling_table) self.state_mins = np.array(self.state_mins) self.state_maxs = np.array(self.state_maxs) self.observation_space = spaces.Box(np.repeat(0, len(self.state_mins)), np.repeat(0, len(self.state_maxs)), dtype=np.float32) self.action_space = spaces.Box(low=-1, high=1, shape=(1, ), dtype=np.float32) self.episode_number = 1 # Price of the electricity schedule self.electricity_price_schedule = pd.read_csv( self.directory + '\\supportFiles\\' + self.price_schedule_name, header=None) self.cooling_load_predictions = pd.read_csv( self.directory + '\\supportFiles\\prediction-cooling_load_perfect.csv') self.electricity_price_predictions = pd.read_csv( self.directory + '\\supportFiles\\prediction-electricity_price_perfect.csv') self.pv_power_generation_predictions = pd.read_csv( self.directory + '\\supportFiles\\prediction-pv_power_generation_perfect.csv') self.max_price = self.electricity_price_schedule.values.max() self.min_price = self.electricity_price_schedule.values.min() # PV & Battery Initialization self.pv = PV(nominal_power=self.pv_nominal_power, tilt_angle=33, azimuth=180 - 64) self.battery = Battery(max_capacity=self.battery_size, rte=0.96) self.eta_ac_dc = 0.9 self.SOC = 1 # Lists for adding variables to eplus output (.csv) self.action_list = [] self.reward_list = [] self.price_list = [] self.tank_soc_list = [] self.battery_soc_list = [] self.incidence_list = [] self.zenith_list = [] self.efficiency_list = [] self.pv_power_generation_list = [] self.pv_energy_production_list = [] self.pv_energy_to_building_list = [] self.pv_energy_to_grid_list = [] self.pv_energy_to_battery_list = [] self.grid_energy_list = [] self.grid_energy_to_building_list = [] self.grid_energy_to_battery_list = [] self.battery_energy_to_building_list = [] self.p_cool_list = [] self.building_energy_consumption_list = [] self.savings_list = [] self.grid_list = [] self.energy_cost_from_grid_list = [] self.energy_cost_to_grid_list = [] self.episode_electricity_cost = 0
idf_notemptyfile = IDF(fhandle) # initialize the IDF object with the file handle idf_notemptyfile.printidf() # <markdowncell> # Aha ! # # Now let us give it a file name # <codecell> # - give it a file name idf_notemptyfile.idfname = "notemptyfile.idf" # - Save it to the disk idf_notemptyfile.save() # <markdowncell> # Let us confirm that the file was saved to disk # <codecell> txt = open("notemptyfile.idf", 'r').read()# read the file from the disk print(txt) # <markdowncell> # Yup ! that file was saved. Let us delete it since we were just playing # <codecell>
def auto_generate_from_template(peak_heating_w, peak_cooling_w, base_idf_dir, final_idf_dir, idd_file_dir): IDF.setiddname(idd_file_dir) idf = IDF(base_idf_dir) idf = auto_update_LP_flow_rates(idf, peak_heating_w, peak_cooling_w) idf.save(final_idf_dir)
def __create_empty_idf(self): idfstring = idf_strings.version.format(get_eplus_version(ep_config=self._cfg)) fhandle = StringIO(idfstring) idf = IDF(fhandle) idf.save(str(self.idf_file_path))
archivoIDD = sys.argv[1] archivoIDF = sys.argv[2] rutaMateriales = sys.argv[3] IDF.setiddname(archivoIDD) idf = IDF(archivoIDF) materiales = idf.idfobjects['MATERIAL'] modificaciones = [] for argumento in sys.argv[4:]: modificaciones.append(argumento) archivoMateriales = open(rutaMateriales, "r") listaMateriales = archivoMateriales.read().splitlines() i = 0 for linea in listaMateriales: for material in materiales: if (str(material.Name) == linea): material.Thickness = modificaciones[i] material.Conductivity = modificaciones[i + 1] material.Density = modificaciones[i + 2] material.Specific_Heat = modificaciones[i + 3] material.Thermal_Absorptance = modificaciones[i + 4] material.Solar_Absorptance = modificaciones[i + 5] material.Visible_Absorptance = modificaciones[i + 6] i += 7 archivoMateriales.close() idf.save()
def createrectshading(idd_filename, idf_filename, base_surface, shading_str, start_point, end_point, depths): ########################################## # loading base surface data from idf file ########################################## # check if IDD has been already set try: IDF.setiddname(idd_filename) except modeleditor.IDDAlreadySetError as e: pass # load idf file into idf collection idf_collection = IDF(idf_filename) # find the named base_surface in idf collection walls = idf_collection.idfobjects['BuildingSurface:Detailed'.upper()] for wall in walls: if wall.Name == base_surface: # named base_surface is now contained in wall break else: # named base_surface was not found in idf file print('epnurbs.createrectshading: unable to find the base surface', base_surface, 'in', idf_filename) return ############################################################################## # feet of perpendiculars from the start and the end point to the base surface ############################################################################## # getting the found base_surface's coordinates coord = wall.coords ulc = coord[0] blc = coord[1] brc = coord[2] # find the base_surface's plane normal and normalize it N = crossproduct( (blc[0]-ulc[0], blc[1]-ulc[1], blc[2]-ulc[2]), \ (brc[0]-ulc[0], brc[1]-ulc[1], brc[2]-ulc[2]) ) N = normalize(N) # calculate feet of perpendiculars start_foot = foot(start_point, ulc, N) end_foot = foot(end_point, ulc, N) # steps between the start and the end point num = len(depths) step = [(end_foot[0] - start_foot[0]) / num, (end_foot[1] - start_foot[1]) / num, (end_foot[2] - start_foot[2]) / num] ######################################################################## # create string of idf definitions for a sequence of shading rectangles ######################################################################## idf_total_shading_def = "" for i in range(num): if depths[i] > 0.01: # two base_surface vertices are start_foot + i*step and start_foot + (i+1)*step # the other two vertices are at depth[i] distance from the base surface v1 = [ start_foot[0] + i * step[0], start_foot[1] + i * step[1], start_foot[2] + i * step[2] ] v2 = [ v1[0] + depths[i] * N[0], v1[1] + depths[i] * N[1], v1[2] + depths[i] * N[2] ] v4 = [ start_foot[0] + (i + 1) * step[0], start_foot[1] + (i + 1) * step[1], start_foot[2] + (i + 1) * step[2] ] v3 = [ v4[0] + depths[i] * N[0], v4[1] + depths[i] * N[1], v4[2] + depths[i] * N[2] ] vertices_str = "{:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}".format( v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2], v4[0], v4[1], v4[2]) countervertices_str = "{:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}".format( v4[0], v4[1], v4[2], v3[0], v3[1], v3[2], v2[0], v2[1], v2[2], v1[0], v1[1], v1[2]) single_shading_def = shading_str.replace('<IDX>', str(i)).replace( '<BASESURFACE>', base_surface).replace('<VERTICES>', vertices_str).replace( '<COUNTERVERTICES>', countervertices_str) idf_total_shading_def = idf_total_shading_def + single_shading_def else: # we do not have a shading rectangle if it is not deep enough pass # create idf shading objects from the string containing shading definitions from io import StringIO idf_shading = IDF(StringIO(idf_total_shading_def)) # copy idf shading objects to the existing idf file shadings = idf_shading.idfobjects["SHADING:ZONE:DETAILED"] for shading in shadings: idf_collection.copyidfobject(shading) ############################### # at the end, save the changes ############################### idf_collection.save()
# <markdowncell> # There are 3 fruits in the list. # <headingcell level=2> # Saving an idf file # <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>
fhandle) # initialize the IDF object with the file handle idf_notemptyfile.printidf() # <markdowncell> # Aha ! # # Now let us give it a file name # <codecell> # - give it a file name idf_notemptyfile.idfname = "notemptyfile.idf" # - Save it to the disk idf_notemptyfile.save() # <markdowncell> # Let us confirm that the file was saved to disk # <codecell> txt = open("notemptyfile.idf", "r").read() # read the file from the disk print(txt) # <markdowncell> # Yup ! that file was saved. Let us delete it since we were just playing # <codecell>
def createnurbsshading(idd_filename, idf_filename, base_surface, shading_str, ctrl_points, evaluated_points=20): ########################################## # loading base surface data from idf file ########################################## # check if IDD has been already set try: IDF.setiddname(idd_filename) except modeleditor.IDDAlreadySetError as e: pass # load idf file into idf collection idf_collection = IDF(idf_filename) # find the named base_surface in idf collection walls = idf_collection.idfobjects['BuildingSurface:Detailed'.upper()] for wall in walls: if wall.Name == base_surface: # named base_surface is now contained in wall break else: # named base_surface was not found in idf file print('epnurbs.createshading: unable to find the base surface', base_surface, 'in', idf_filename) return ################################# # calculating NURBS curve points ################################# from geomdl import NURBS from geomdl import utilities curve = NURBS.Curve() # 1/delta corresponds to the number of trapezoids used in approximation of NURBS shading curve.delta = 1/evaluated_points curve.degree = 3 # add weight 1 to each control point # unless it has been already weighted for cpt in ctrl_points: if len(cpt)<4: cpt.append(1.0) # sets curve control points curve.set_ctrlpts(ctrl_points) # sets curve knot vector curve.knotvector = utilities.generate_knot_vector(curve.degree, len(curve.ctrlpts)) # evaluates curve points curve.evaluate() # make a local copy of evaluated curve points crv_points = curve.curvepts ################################################################################### # feet of perpendiculars from the remaining NURBS curve points to the base surface ################################################################################### # getting the found base_surface's coordinates coord = wall.coords ulc = coord[0] blc = coord[1] brc = coord[2] # find the base_surface's plane normal and normalize it N = crossproduct( (blc[0]-ulc[0], blc[1]-ulc[1], blc[2]-ulc[2]), \ (brc[0]-ulc[0], brc[1]-ulc[1], brc[2]-ulc[2]) ) N = normalize(N) # calculate feet of perpendiculars feet_points = [foot(crv_points[i], ulc, N) for i in range(len(crv_points))] ################################################################################# # create string of idf definitions for trapezoids that approximate NURBS shading ################################################################################# idf_total_shading_def = "" for i in range(1, len(crv_points)): # the width of a trapezoid must be at least 0.01 if distance(crv_points[i-1], crv_points[i])>=0.01 and \ distance(feet_points[i-1], feet_points[i])>=0.01: # are trapezoid arms at least 0.01 or do we have a triangle? if distance(crv_points[i-1], feet_points[i-1])>=0.01: if distance(crv_points[i], feet_points[i])>=0.01: # both arms are at least 0.01, so we have a trapezoid vertices_str = "{:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}".format( feet_points[i-1][0], feet_points[i-1][1], feet_points[i-1][2], crv_points[i-1][0], crv_points[i-1][1], crv_points[i-1][2], crv_points[i][0], crv_points[i][1], crv_points[i][2], feet_points[i][0], feet_points[i][1], feet_points[i][2]) countervertices_str = "{:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}".format( feet_points[i][0], feet_points[i][1], feet_points[i][2], crv_points[i][0], crv_points[i][1], crv_points[i][2], crv_points[i-1][0], crv_points[i-1][1], crv_points[i-1][2], feet_points[i-1][0], feet_points[i-1][1], feet_points[i-1][2]) single_shading_def = shading_str.replace('<IDX>', str(i)).replace('<BASESURFACE>', base_surface).replace('<VERTICES>', vertices_str).replace('<COUNTERVERTICES>', countervertices_str) idf_total_shading_def = idf_total_shading_def + single_shading_def else: # arm i is less than 0.01, so we have a triangle vertices_str = "{:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}".format( feet_points[i-1][0], feet_points[i-1][1], feet_points[i-1][2], crv_points[i-1][0], crv_points[i-1][1], crv_points[i-1][2], feet_points[i][0], feet_points[i][1], feet_points[i][2]) countervertices_str = "{:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}".format( feet_points[i][0], feet_points[i][1], feet_points[i][2], crv_points[i-1][0], crv_points[i-1][1], crv_points[i-1][2], feet_points[i-1][0], feet_points[i-1][1], feet_points[i-1][2]) single_shading_def = shading_str.replace('<IDX>', str(i)).replace('<BASESURFACE>', base_surface).replace('<VERTICES>', vertices_str).replace('<COUNTERVERTICES>', countervertices_str) idf_total_shading_def = idf_total_shading_def + single_shading_def else: # arm i-1 is less than 0.01, but do we still have a triangle? if distance(crv_points[i], feet_points[i])>=0.01: # we have a triangle vertices_str = "{:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}".format( feet_points[i-1][0], feet_points[i-1][1], feet_points[i-1][2], crv_points[i][0], crv_points[i][1], crv_points[i][2], feet_points[i][0], feet_points[i][1], feet_points[i][2]) countervertices_str = "{:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}".format( feet_points[i][0], feet_points[i][1], feet_points[i][2], crv_points[i][0], crv_points[i][1], crv_points[i][2], feet_points[i-1][0], feet_points[i-1][1], feet_points[i-1][2]) single_shading_def = shading_str.replace('<IDX>', str(i)).replace('<BASESURFACE>', base_surface).replace('<VERTICES>', vertices_str).replace('<COUNTERVERTICES>', countervertices_str) idf_total_shading_def = idf_total_shading_def + single_shading_def else: # we do not have a shading element in this case pass # create idf shading objects from the string containing shading definitions from io import StringIO idf_shading = IDF(StringIO(idf_total_shading_def)) # copy idf shading objects to the existing idf file shadings = idf_shading.idfobjects["SHADING:ZONE:DETAILED"] for shading in shadings: idf_collection.copyidfobject(shading) ############################### # at the end, save the changes ############################### idf_collection.save()
def GeoGen(sheet): num_of_zones = sheet.Range("A7").Value construction_template = sheet.Range("AN7").Value #Initialize a blank idf file ts = time.time() #st = datetime.datetime.fromtimestamp(ts).strftime('%Y%m%d %H%M%S') st = datetime.datetime.fromtimestamp(ts).strftime('%Y%m%d-%H%M') blankstr = "" new_idf = IDF(StringIO(blankstr)) new_idf.idfname = "NongeoXport " + st + ".idf" #Import Constructoin Templates const_fname = "ahshrae901_construction_templates.idf" my_const = IDF(const_fname) #Copy All Construction Templates into New idf file materials = my_const.idfobjects['material'.upper()] for i in range(len(materials)): new_idf.copyidfobject(materials[i]) materials_nomass = my_const.idfobjects['material:nomass'.upper()] for i in range(len(materials_nomass)): new_idf.copyidfobject(materials_nomass[i]) materials_airgap = my_const.idfobjects['material:airgap'.upper()] for i in range(len(materials_airgap)): new_idf.copyidfobject(materials_airgap[i]) window_materials_sgs = my_const.idfobjects[ 'windowmaterial:simpleglazingsystem'.upper()] for i in range(len(window_materials_sgs)): new_idf.copyidfobject(window_materials_sgs[i]) window_materials_glz = my_const.idfobjects[ 'windowmaterial:glazing'.upper()] for i in range(len(window_materials_glz)): new_idf.copyidfobject(window_materials_glz[i]) constructions = my_const.idfobjects['construction'.upper()] for i in range(len(constructions)): new_idf.copyidfobject(constructions[i]) #Assign Surface Construction Names Based on User Templates Selections interior_floor_const = "Interior Floor" interior_wall_const = "Interior Wall" interior_ceiling_const = "Interior Ceiling" exterior_floor_const = "ExtSlabCarpet 4in ClimateZone 1-8" if construction_template == "ASHRAE 90.1 2010 Climate Zone 1": exterior_wall_const = "ASHRAE 90.1-2010 ExtWall Mass ClimateZone 1" exterior_window_const = "ASHRAE 90.1-2010 ExtWindow Metal ClimateZone 1" exterior_roof_const = "ASHRAE 90.1-2010 ExtRoof IEAD ClimateZone 1" elif construction_template == "ASHRAE 90.1 2010 Climate Zone 2": exterior_wall_const = "ASHRAE 90.1-2010 ExtWall Mass ClimateZone 2" exterior_window_const = "ASHRAE 90.1-2010 ExtWindow Metal ClimateZone 2" exterior_roof_const = "ASHRAE 90.1-2010 ExtRoof IEAD ClimateZone 2-8" elif construction_template == "ASHRAE 90.1 2010 Climate Zone 3": exterior_wall_const = "ASHRAE 90.1-2010 ExtWall Mass ClimateZone 3" exterior_window_const = "ASHRAE 90.1-2010 ExtWindow Metal ClimateZone 3" exterior_roof_const = "ASHRAE 90.1-2010 ExtRoof IEAD ClimateZone 2-8" elif construction_template == "ASHRAE 90.1 2010 Climate Zone 4": exterior_wall_const = "ASHRAE 90.1-2010 ExtWall Mass ClimateZone 4" exterior_window_const = "ASHRAE 90.1-2010 ExtWindow Metal ClimateZone 4-6" exterior_roof_const = "ASHRAE 90.1-2010 ExtRoof IEAD ClimateZone 2-8" elif construction_template == "ASHRAE 90.1 2010 Climate Zone 5": exterior_wall_const = "ASHRAE 90.1-2010 ExtWall Mass ClimateZone 5" exterior_window_const = "ASHRAE 90.1-2010 ExtWindow Metal ClimateZone 4-6" exterior_roof_const = "ASHRAE 90.1-2010 ExtRoof IEAD ClimateZone 2-8" elif construction_template == "ASHRAE 90.1 2010 Climate Zone 6": exterior_wall_const = "ASHRAE 90.1-2010 ExtWall Mass ClimateZone 6" exterior_window_const = "ASHRAE 90.1-2010 ExtWindow Metal ClimateZone 4-6" exterior_roof_const = "ASHRAE 90.1-2010 ExtRoof IEAD ClimateZone 2-8" elif construction_template == "ASHRAE 90.1 2010 Climate Zone 7": exterior_wall_const = "ASHRAE 90.1-2010 ExtWall Mass ClimateZone 7-8" exterior_window_const = "ASHRAE 90.1-2010 ExtWindow Metal ClimateZone 7-8" exterior_roof_const = "ASHRAE 90.1-2010 ExtRoof IEAD ClimateZone 2-8" elif construction_template == "ASHRAE 90.1 2010 Climate Zone 8": exterior_wall_const = "ASHRAE 90.1-2010 ExtWall Mass ClimateZone 7-8" exterior_window_const = "ASHRAE 90.1-2010 ExtWindow Metal ClimateZone 7-8" exterior_roof_const = "ASHRAE 90.1-2010 ExtRoof IEAD ClimateZone 2-8" ####Start Writing idf Objects ##General idf Objects for IDFXporter #Define Version Objects version = new_idf.newidfobject("version".upper()) version.Version_Identifier = 8.5 #Define Simulation Control Objects simctrl = new_idf.newidfobject("simulationcontrol".upper()) simctrl.Do_Zone_Sizing_Calculation = "Yes" simctrl.Do_System_Sizing_Calculation = "Yes" simctrl.Do_Plant_Sizing_Calculation = "Yes" simctrl.Run_Simulation_for_Sizing_Periods = "No" simctrl.Run_Simulation_for_Weather_File_Run_Periods = "Yes" #Define Building Object building = new_idf.newidfobject("building".upper()) building.Name = "My Building" building.North_Axis = 0 #Define Run Periods Object run_period = new_idf.newidfobject("runperiod".upper()) run_period.Name = "Run Period 1" run_period.Begin_Month = 1 run_period.Begin_Day_of_Month = 1 run_period.End_Month = 12 run_period.End_Day_of_Month = 31 run_period.Day_of_Week_for_Start_Day = "Thursday" run_period.Use_Weather_File_Rain_Indicators = "Yes" run_period.Use_Weather_File_Snow_Indicators = "Yes" #Define Schedule Type Limits Objects sch_tp_limit_1 = new_idf.newidfobject("scheduletypelimits".upper()) sch_tp_limit_1.Name = "Any Number" sch_tp_limit_2 = new_idf.newidfobject("scheduletypelimits".upper()) sch_tp_limit_2.Name = "Fraction" sch_tp_limit_3 = new_idf.newidfobject("scheduletypelimits".upper()) sch_tp_limit_3.Name = "Temperature" sch_tp_limit_4 = new_idf.newidfobject("scheduletypelimits".upper()) sch_tp_limit_4.Name = "On/Off" sch_tp_limit_5 = new_idf.newidfobject("scheduletypelimits".upper()) sch_tp_limit_5.Name = "Control Type" sch_tp_limit_6 = new_idf.newidfobject("scheduletypelimits".upper()) sch_tp_limit_6.Name = "Humidity" sch_tp_limit_7 = new_idf.newidfobject("scheduletypelimits".upper()) sch_tp_limit_7.Name = "Number" ##Additional idf Objects from Params #Define Shadow Calculation Objects shadow_calc = new_idf.newidfobject("shadowcalculation".upper()) shadow_calc.Calculation_Method = "AverageOverDaysInFrequency" #Define SurfaceConvectionAlgorithm:Inside Objects surf_conv_algorithm_in = new_idf.newidfobject( "SurfaceConvectionAlgorithm:Inside".upper()) surf_conv_algorithm_in.Algorithm = "TARP" #Define SurfaceConvectionAlgorithm:Outside Objects surf_conv_algorithm_out = new_idf.newidfobject( "SurfaceConvectionAlgorithm:Outside".upper()) surf_conv_algorithm_out.Algorithm = "DOE-2" #Define HeatBalanceAlgorithm Objects hb_algorithm = new_idf.newidfobject("HeatBalanceAlgorithm".upper()) hb_algorithm.Algorithm = "ConductionTransferFunction" #Define SurfaceProperty:OtherSideConditionsModel Objects surf_prop_oscm = new_idf.newidfobject( "SurfaceProperty:OtherSideConditionsModel".upper()) surf_prop_oscm.Name = "GapConvectionModel" #Define ConvergenceLimits Objects conv_limits = new_idf.newidfobject("ConvergenceLimits".upper()) conv_limits.Minimum_System_Timestep = 0 #Define Global Geometry Rules Objects rule = new_idf.newidfobject("globalgeometryrules".upper()) rule.Starting_Vertex_Position = "UpperLeftCorner" rule.Vertex_Entry_Direction = "Counterclockwise" rule.Coordinate_System = "Relative" rule.Daylighting_Reference_Point_Coordinate_System = "Relative" rule.Rectangular_Surface_Coordinate_System = "Relative" #Define SizingParameters Objects szparams = new_idf.newidfobject("sizing:parameters".upper()) szparams.Heating_Sizing_Factor = 1.25 szparams.Cooling_Sizing_Factor = 1.15 ####Non-Geometric Generator Starts for id in range(7, int(7 + num_of_zones)): zone_name = sheet.Range("B" + str(id)).Value # zone_name = "Thermal Zone: " + zone_name # zone_name = zone_name zone_origin_x = sheet.Range("C" + str(id)).Value zone_origin_y = sheet.Range("D" + str(id)).Value zone_origin_z = sheet.Range("E" + str(id)).Value # prmtr_or_not = sheet.Range("F"+str(id)).Value roof_or_not = sheet.Range("M" + str(id)).Value zone_height = sheet.Range("H" + str(id)).Value zone_length = sheet.Range("I" + str(id)).Value zone_width = sheet.Range("G" + str(id)).Value / sheet.Range("I" + str(id)).Value prmtr1_normal = sheet.Range("K" + str(id)).Value prmtr2_normal = sheet.Range("L" + str(id)).Value grndflr_or_not = sheet.Range("N" + str(id)).Value wind2wall_ratio = sheet.Range("O" + str(id)).Value wind_sill_height = sheet.Range("P" + str(id)).Value #Define Zone Objects zone = new_idf.newidfobject("zone".upper()) zone.Name = zone_name zone.X_Origin = zone_origin_x zone.Y_Origin = zone_origin_y zone.Z_Origin = zone_origin_z zone.Ceiling_Height = zone_height #Define BuildingSurface:Detailed Objects, default as adiabatic, and interior constructions surface_1 = new_idf.newidfobject("buildingsurface:detailed".upper()) surface_1.Name = zone_name + " Surface 1" surface_1.Surface_Type = "Floor" surface_1.Construction_Name = interior_floor_const surface_1.Zone_Name = zone_name surface_1.Outside_Boundary_Condition = "Adiabatic" surface_1.Sun_Exposure = "NoSun" surface_1.Wind_Exposure = "NoWind" surface_1.Vertex_1_Xcoordinate = zone_length surface_1.Vertex_1_Ycoordinate = zone_width surface_1.Vertex_1_Zcoordinate = 0 surface_1.Vertex_2_Xcoordinate = zone_length surface_1.Vertex_2_Ycoordinate = 0 surface_1.Vertex_2_Zcoordinate = 0 surface_1.Vertex_3_Xcoordinate = 0 surface_1.Vertex_3_Ycoordinate = 0 surface_1.Vertex_3_Zcoordinate = 0 surface_1.Vertex_4_Xcoordinate = 0 surface_1.Vertex_4_Ycoordinate = zone_width surface_1.Vertex_4_Zcoordinate = 0 surface_2 = new_idf.newidfobject("buildingsurface:detailed".upper()) surface_2.Name = zone_name + " Surface 2" surface_2.Surface_Type = "Wall" surface_2.Construction_Name = interior_wall_const surface_2.Zone_Name = zone_name surface_2.Outside_Boundary_Condition = "Adiabatic" surface_2.Sun_Exposure = "NoSun" surface_2.Wind_Exposure = "NoWind" surface_2.Vertex_1_Xcoordinate = 0 surface_2.Vertex_1_Ycoordinate = zone_width surface_2.Vertex_1_Zcoordinate = zone_height surface_2.Vertex_2_Xcoordinate = 0 surface_2.Vertex_2_Ycoordinate = zone_width surface_2.Vertex_2_Zcoordinate = 0 surface_2.Vertex_3_Xcoordinate = 0 surface_2.Vertex_3_Ycoordinate = 0 surface_2.Vertex_3_Zcoordinate = 0 surface_2.Vertex_4_Xcoordinate = 0 surface_2.Vertex_4_Ycoordinate = 0 surface_2.Vertex_4_Zcoordinate = zone_height surface_3 = new_idf.newidfobject("buildingsurface:detailed".upper()) surface_3.Name = zone_name + " Surface 3" surface_3.Surface_Type = "Wall" surface_3.Construction_Name = interior_wall_const surface_3.Zone_Name = zone_name surface_3.Outside_Boundary_Condition = "Adiabatic" surface_3.Sun_Exposure = "NoSun" surface_3.Wind_Exposure = "NoWind" surface_3.Vertex_1_Xcoordinate = zone_length surface_3.Vertex_1_Ycoordinate = zone_width surface_3.Vertex_1_Zcoordinate = zone_height surface_3.Vertex_2_Xcoordinate = zone_length surface_3.Vertex_2_Ycoordinate = zone_width surface_3.Vertex_2_Zcoordinate = 0 surface_3.Vertex_3_Xcoordinate = 0 surface_3.Vertex_3_Ycoordinate = zone_width surface_3.Vertex_3_Zcoordinate = 0 surface_3.Vertex_4_Xcoordinate = 0 surface_3.Vertex_4_Ycoordinate = zone_width surface_3.Vertex_4_Zcoordinate = zone_height surface_4 = new_idf.newidfobject("buildingsurface:detailed".upper()) surface_4.Name = zone_name + " Surface 4" surface_4.Surface_Type = "Wall" surface_4.Construction_Name = interior_wall_const surface_4.Zone_Name = zone_name surface_4.Outside_Boundary_Condition = "Adiabatic" surface_4.Sun_Exposure = "NoSun" surface_4.Wind_Exposure = "NoWind" surface_4.Vertex_1_Xcoordinate = zone_length surface_4.Vertex_1_Ycoordinate = 0 surface_4.Vertex_1_Zcoordinate = zone_height surface_4.Vertex_2_Xcoordinate = zone_length surface_4.Vertex_2_Ycoordinate = 0 surface_4.Vertex_2_Zcoordinate = 0 surface_4.Vertex_3_Xcoordinate = zone_length surface_4.Vertex_3_Ycoordinate = zone_width surface_4.Vertex_3_Zcoordinate = 0 surface_4.Vertex_4_Xcoordinate = zone_length surface_4.Vertex_4_Ycoordinate = zone_width surface_4.Vertex_4_Zcoordinate = zone_height surface_5 = new_idf.newidfobject("buildingsurface:detailed".upper()) surface_5.Name = zone_name + " Surface 5" surface_5.Surface_Type = "Wall" surface_5.Construction_Name = interior_wall_const surface_5.Zone_Name = zone_name surface_5.Outside_Boundary_Condition = "Adiabatic" surface_5.Sun_Exposure = "NoSun" surface_5.Wind_Exposure = "NoWind" surface_5.Vertex_1_Xcoordinate = 0 surface_5.Vertex_1_Ycoordinate = 0 surface_5.Vertex_1_Zcoordinate = zone_height surface_5.Vertex_2_Xcoordinate = 0 surface_5.Vertex_2_Ycoordinate = 0 surface_5.Vertex_2_Zcoordinate = 0 surface_5.Vertex_3_Xcoordinate = zone_length surface_5.Vertex_3_Ycoordinate = 0 surface_5.Vertex_3_Zcoordinate = 0 surface_5.Vertex_4_Xcoordinate = zone_length surface_5.Vertex_4_Ycoordinate = 0 surface_5.Vertex_4_Zcoordinate = zone_height surface_6 = new_idf.newidfobject("buildingsurface:detailed".upper()) surface_6.Name = zone_name + " Surface 6" surface_6.Zone_Name = zone_name surface_6.Vertex_1_Xcoordinate = zone_length surface_6.Vertex_1_Ycoordinate = 0 surface_6.Vertex_1_Zcoordinate = zone_height surface_6.Vertex_2_Xcoordinate = zone_length surface_6.Vertex_2_Ycoordinate = zone_width surface_6.Vertex_2_Zcoordinate = zone_height surface_6.Vertex_3_Xcoordinate = 0 surface_6.Vertex_3_Ycoordinate = zone_width surface_6.Vertex_3_Zcoordinate = zone_height surface_6.Vertex_4_Xcoordinate = 0 surface_6.Vertex_4_Ycoordinate = 0 surface_6.Vertex_4_Zcoordinate = zone_height #Change Surface Type if Roof if roof_or_not == "y": surface_6.Surface_Type = "Roof" surface_6.Construction_Name = exterior_roof_const surface_6.Outside_Boundary_Condition = "Outdoors" surface_6.Sun_Exposure = "SunExposed" surface_6.Wind_Exposure = "WindExposed" else: surface_6.Surface_Type = "Ceiling" surface_6.Construction_Name = interior_ceiling_const surface_6.Outside_Boundary_Condition = "Adiabatic" surface_6.Sun_Exposure = "NoSun" surface_6.Wind_Exposure = "NoWind" #Change Surface Type if Ground Floor if grndflr_or_not == "y": surface_1.Construction_Name = exterior_floor_const surface_1.Outside_Boundary_Condition = "Ground" else: pass #Change Surface Type if Perimeter 1 Normal is non-zero if prmtr1_normal == 0: surface_3.Construction_Name = exterior_wall_const surface_3.Outside_Boundary_Condition = "Outdoors" surface_3.Sun_Exposure = "SunExposed" surface_3.Wind_Exposure = "WindExposed" if wind2wall_ratio > 0: sub_surface = new_idf.newidfobject( "FenestrationSurface:Detailed".upper()) sub_surface.Name = zone_name + " Sub Surface 3" sub_surface.Surface_Type = "Window" sub_surface.Construction_Name = exterior_window_const sub_surface.Building_Surface_Name = surface_3.Name sub_surface.Vertex_1_Xcoordinate = zone_length - 0.0254 sub_surface.Vertex_1_Ycoordinate = zone_width sub_surface.Vertex_1_Zcoordinate = zone_length * zone_height * wind2wall_ratio / ( zone_length - 0.0254 * 2) + wind_sill_height sub_surface.Vertex_2_Xcoordinate = zone_length - 0.0254 sub_surface.Vertex_2_Ycoordinate = zone_width sub_surface.Vertex_2_Zcoordinate = wind_sill_height sub_surface.Vertex_3_Xcoordinate = 0.0254 sub_surface.Vertex_3_Ycoordinate = zone_width sub_surface.Vertex_3_Zcoordinate = wind_sill_height sub_surface.Vertex_4_Xcoordinate = 0.0254 sub_surface.Vertex_4_Ycoordinate = zone_width sub_surface.Vertex_4_Zcoordinate = sub_surface.Vertex_1_Zcoordinate else: pass elif prmtr1_normal == 90: surface_4.Construction_Name = exterior_wall_const surface_4.Outside_Boundary_Condition = "Outdoors" surface_4.Sun_Exposure = "SunExposed" surface_4.Wind_Exposure = "WindExposed" if wind2wall_ratio > 0: sub_surface = new_idf.newidfobject( "FenestrationSurface:Detailed".upper()) sub_surface.Name = zone_name + " Sub Surface 4" sub_surface.Surface_Type = "Window" sub_surface.Construction_Name = exterior_window_const sub_surface.Building_Surface_Name = surface_4.Name sub_surface.Vertex_1_Xcoordinate = zone_length sub_surface.Vertex_1_Ycoordinate = 0.0254 sub_surface.Vertex_1_Zcoordinate = zone_width * zone_height * wind2wall_ratio / ( zone_width - 0.0254 * 2) + wind_sill_height # sub_surface.Vertex_1_Zcoordinate = zone_length*zone_height*wind2wall_ratio/sub_surface.Vertex_1_Xcoordinate+wind_sill_height sub_surface.Vertex_2_Xcoordinate = zone_length sub_surface.Vertex_2_Ycoordinate = 0.0254 sub_surface.Vertex_2_Zcoordinate = wind_sill_height sub_surface.Vertex_3_Xcoordinate = zone_length sub_surface.Vertex_3_Ycoordinate = zone_width - 0.0254 sub_surface.Vertex_3_Zcoordinate = wind_sill_height sub_surface.Vertex_4_Xcoordinate = zone_length sub_surface.Vertex_4_Ycoordinate = zone_width - 0.0254 sub_surface.Vertex_4_Zcoordinate = sub_surface.Vertex_1_Zcoordinate else: pass elif prmtr1_normal == 180: surface_5.Construction_Name = exterior_wall_const surface_5.Outside_Boundary_Condition = "Outdoors" surface_5.Sun_Exposure = "SunExposed" surface_5.Wind_Exposure = "WindExposed" if wind2wall_ratio > 0: sub_surface = new_idf.newidfobject( "FenestrationSurface:Detailed".upper()) sub_surface.Name = zone_name + " Sub Surface 5" sub_surface.Surface_Type = "Window" sub_surface.Construction_Name = exterior_window_const sub_surface.Building_Surface_Name = surface_5.Name sub_surface.Vertex_1_Xcoordinate = 0.0254 sub_surface.Vertex_1_Ycoordinate = 0 sub_surface.Vertex_1_Zcoordinate = zone_length * zone_height * wind2wall_ratio / ( zone_length - 0.0254 * 2) + wind_sill_height # sub_surface.Vertex_1_Zcoordinate = zone_length*zone_height*wind2wall_ratio/sub_surface.Vertex_1_Xcoordinate+wind_sill_height sub_surface.Vertex_2_Xcoordinate = 0.0254 sub_surface.Vertex_2_Ycoordinate = 0 sub_surface.Vertex_2_Zcoordinate = wind_sill_height sub_surface.Vertex_3_Xcoordinate = zone_length - 0.0254 sub_surface.Vertex_3_Ycoordinate = 0 sub_surface.Vertex_3_Zcoordinate = wind_sill_height sub_surface.Vertex_4_Xcoordinate = zone_length - 0.0254 sub_surface.Vertex_4_Ycoordinate = 0 sub_surface.Vertex_4_Zcoordinate = sub_surface.Vertex_1_Zcoordinate else: pass elif prmtr1_normal == 270: surface_2.Construction_Name = exterior_wall_const surface_2.Outside_Boundary_Condition = "Outdoors" surface_2.Sun_Exposure = "SunExposed" surface_2.Wind_Exposure = "WindExposed" if wind2wall_ratio > 0: sub_surface = new_idf.newidfobject( "FenestrationSurface:Detailed".upper()) sub_surface.Name = zone_name + " Sub Surface 2" sub_surface.Surface_Type = "Window" sub_surface.Construction_Name = exterior_window_const sub_surface.Building_Surface_Name = surface_2.Name sub_surface.Vertex_1_Xcoordinate = 0 sub_surface.Vertex_1_Ycoordinate = zone_width - 0.0254 sub_surface.Vertex_1_Zcoordinate = zone_width * zone_height * wind2wall_ratio / ( zone_width - 2 * 0.0254) + wind_sill_height # sub_surface.Vertex_1_Zcoordinate = zone_length*zone_height*wind2wall_ratio/sub_surface.Vertex_1_Xcoordinate+wind_sill_height sub_surface.Vertex_2_Xcoordinate = 0 sub_surface.Vertex_2_Ycoordinate = zone_width - 0.0254 sub_surface.Vertex_2_Zcoordinate = wind_sill_height sub_surface.Vertex_3_Xcoordinate = 0 sub_surface.Vertex_3_Ycoordinate = 0.0254 sub_surface.Vertex_3_Zcoordinate = wind_sill_height sub_surface.Vertex_4_Xcoordinate = 0 sub_surface.Vertex_4_Ycoordinate = 0.0254 sub_surface.Vertex_4_Zcoordinate = sub_surface.Vertex_1_Zcoordinate else: pass else: pass #Change Surface Type if Perimeter 2 Normal is non-zero if prmtr2_normal == 0: surface_3.Construction_Name = exterior_wall_const surface_3.Outside_Boundary_Condition = "Outdoors" surface_3.Sun_Exposure = "SunExposed" surface_3.Wind_Exposure = "WindExposed" if wind2wall_ratio > 0: sub_surface = new_idf.newidfobject( "FenestrationSurface:Detailed".upper()) sub_surface.Name = zone_name + " Sub Surface 3" sub_surface.Surface_Type = "Window" sub_surface.Construction_Name = exterior_window_const sub_surface.Building_Surface_Name = surface_3.Name sub_surface.Vertex_1_Xcoordinate = zone_length - 0.0254 sub_surface.Vertex_1_Ycoordinate = zone_width sub_surface.Vertex_1_Zcoordinate = zone_length * zone_height * wind2wall_ratio / ( zone_length - 0.0254 * 2) + wind_sill_height sub_surface.Vertex_2_Xcoordinate = zone_length - 0.0254 sub_surface.Vertex_2_Ycoordinate = zone_width sub_surface.Vertex_2_Zcoordinate = wind_sill_height sub_surface.Vertex_3_Xcoordinate = 0.0254 sub_surface.Vertex_3_Ycoordinate = zone_width sub_surface.Vertex_3_Zcoordinate = wind_sill_height sub_surface.Vertex_4_Xcoordinate = 0.0254 sub_surface.Vertex_4_Ycoordinate = zone_width sub_surface.Vertex_4_Zcoordinate = sub_surface.Vertex_1_Zcoordinate else: pass elif prmtr2_normal == 90: surface_4.Construction_Name = exterior_wall_const surface_4.Outside_Boundary_Condition = "Outdoors" surface_4.Sun_Exposure = "SunExposed" surface_4.Wind_Exposure = "WindExposed" if wind2wall_ratio > 0: sub_surface = new_idf.newidfobject( "FenestrationSurface:Detailed".upper()) sub_surface.Name = zone_name + " Sub Surface 4" sub_surface.Surface_Type = "Window" sub_surface.Construction_Name = exterior_window_const sub_surface.Building_Surface_Name = surface_4.Name sub_surface.Vertex_1_Xcoordinate = zone_length sub_surface.Vertex_1_Ycoordinate = 0.0254 sub_surface.Vertex_1_Zcoordinate = zone_width * zone_height * wind2wall_ratio / ( zone_width - 0.0254 * 2) + wind_sill_height # sub_surface.Vertex_1_Zcoordinate = zone_length*zone_height*wind2wall_ratio/sub_surface.Vertex_1_Xcoordinate+wind_sill_height sub_surface.Vertex_2_Xcoordinate = zone_length sub_surface.Vertex_2_Ycoordinate = 0.0254 sub_surface.Vertex_2_Zcoordinate = wind_sill_height sub_surface.Vertex_3_Xcoordinate = zone_length sub_surface.Vertex_3_Ycoordinate = zone_width - 0.0254 sub_surface.Vertex_3_Zcoordinate = wind_sill_height sub_surface.Vertex_4_Xcoordinate = zone_length sub_surface.Vertex_4_Ycoordinate = zone_width - 0.0254 sub_surface.Vertex_4_Zcoordinate = sub_surface.Vertex_1_Zcoordinate else: pass elif prmtr2_normal == 180: surface_5.Construction_Name = exterior_wall_const surface_5.Outside_Boundary_Condition = "Outdoors" surface_5.Sun_Exposure = "SunExposed" surface_5.Wind_Exposure = "WindExposed" if wind2wall_ratio > 0: sub_surface = new_idf.newidfobject( "FenestrationSurface:Detailed".upper()) sub_surface.Name = zone_name + " Sub Surface 5" sub_surface.Surface_Type = "Window" sub_surface.Construction_Name = exterior_window_const sub_surface.Building_Surface_Name = surface_5.Name sub_surface.Vertex_1_Xcoordinate = 0.0254 sub_surface.Vertex_1_Ycoordinate = 0 sub_surface.Vertex_1_Zcoordinate = zone_length * zone_height * wind2wall_ratio / ( zone_length - 0.0254 * 2) + wind_sill_height # sub_surface.Vertex_1_Zcoordinate = zone_length*zone_height*wind2wall_ratio/sub_surface.Vertex_1_Xcoordinate+wind_sill_height sub_surface.Vertex_2_Xcoordinate = 0.0254 sub_surface.Vertex_2_Ycoordinate = 0 sub_surface.Vertex_2_Zcoordinate = wind_sill_height sub_surface.Vertex_3_Xcoordinate = zone_length - 0.0254 sub_surface.Vertex_3_Ycoordinate = 0 sub_surface.Vertex_3_Zcoordinate = wind_sill_height sub_surface.Vertex_4_Xcoordinate = zone_length - 0.0254 sub_surface.Vertex_4_Ycoordinate = 0 sub_surface.Vertex_4_Zcoordinate = sub_surface.Vertex_1_Zcoordinate else: pass elif prmtr2_normal == 270: surface_2.Construction_Name = exterior_wall_const surface_2.Outside_Boundary_Condition = "Outdoors" surface_2.Sun_Exposure = "SunExposed" surface_2.Wind_Exposure = "WindExposed" if wind2wall_ratio > 0: sub_surface = new_idf.newidfobject( "FenestrationSurface:Detailed".upper()) sub_surface.Name = zone_name + " Sub Surface 2" sub_surface.Surface_Type = "Window" sub_surface.Construction_Name = exterior_window_const sub_surface.Building_Surface_Name = surface_2.Name sub_surface.Vertex_1_Xcoordinate = 0 sub_surface.Vertex_1_Ycoordinate = zone_width - 0.0254 sub_surface.Vertex_1_Zcoordinate = zone_width * zone_height * wind2wall_ratio / ( zone_width - 2 * 0.0254) + wind_sill_height # sub_surface.Vertex_1_Zcoordinate = zone_length*zone_height*wind2wall_ratio/sub_surface.Vertex_1_Xcoordinate+wind_sill_height sub_surface.Vertex_2_Xcoordinate = 0 sub_surface.Vertex_2_Ycoordinate = zone_width - 0.0254 sub_surface.Vertex_2_Zcoordinate = wind_sill_height sub_surface.Vertex_3_Xcoordinate = 0 sub_surface.Vertex_3_Ycoordinate = 0.0254 sub_surface.Vertex_3_Zcoordinate = wind_sill_height sub_surface.Vertex_4_Xcoordinate = 0 sub_surface.Vertex_4_Ycoordinate = 0.0254 sub_surface.Vertex_4_Zcoordinate = sub_surface.Vertex_1_Zcoordinate else: pass else: pass new_idf.save() this_idf = new_idf.idfname # dir_path = os.path.dirname(os.path.realpath(this_idf)) # # os.chdir('..') # shutil.copy2(dir_path, '/templates/) # complete target filename given # shutil.copy2('/src/file.ext', '/dst/dir') # target filename is /dst/dir/file.ext pre, ext = os.path.splitext(this_idf) os.rename(this_idf, pre + ".pxt")
def createnurbsopening(idd_filename, idf_filename, base_surface, opening_str, ctrl_points, evaluated_points=50): ########################################## # loading base surface data from idf file ########################################## # check if IDD has been already set try: IDF.setiddname(idd_filename) except modeleditor.IDDAlreadySetError as e: pass # load idf file into idf collection idf_collection = IDF(idf_filename) # find the named base_surface in idf collection walls = idf_collection.idfobjects['BuildingSurface:Detailed'.upper()] for wall in walls: if wall.Name == base_surface: # named base_surface is now contained in wall break else: # named base_surface was not found in idf file print('epnurbs.createopening: unable to find the base surface', base_surface, 'in', idf_filename) return ################################# # calculating NURBS curve points ################################# from geomdl import NURBS from geomdl import utilities # one has to exclude checks for leading zeros and trailing ones in geomdl.utilities.check_knot_vector # in order for this knotvector to be allowed! utilities.check_knot_vector = new_check_knot_vector curve = NURBS.Curve() # 1/delta corresponds to the number of evaluated points of a NURBS curve that defines the opening curve.delta = 1/evaluated_points curve.degree = 3 # add weight 1 to each control point for cpt in ctrl_points: if len(cpt)<4: cpt.append(1.0) # add copy of the first degree control points in order to close NURBS curve extra_points = ctrl_points[:curve.degree] ctrl_points.extend(extra_points) # sets curve control points curve.set_ctrlpts(ctrl_points) # sets knot vector for closed NURBS curve # note that the length of ctrl_points has increased for curve.degree due to extend operation knotstep = 1/(len(ctrl_points) + curve.degree) curve.knotvector = [i*knotstep for i in range(len(ctrl_points)+curve.degree+1)] # note that for the closed NURBS curve # we have to use only the domain [knotvector[curve.degree], knotvector[len(ctrl_points)]]!!! # evaluates curve points curve.evaluate(curve.degree*knotstep, len(ctrl_points)*knotstep) # make a local copy of evaluated curve points crv_points = curve.curvepts ######################################################################### # feet of perpendiculars from the NURBS curve points to the base surface, # just to make sure we are not getting out of its plane ######################################################################### # getting the found base_surface's coordinates coord = wall.coords ulc = coord[0] blc = coord[1] brc = coord[2] # find the base_surface's plane normal and normalize it u = [ blc[0]-ulc[0], blc[1]-ulc[1], blc[2]-ulc[2] ] v = [ brc[0]-blc[0], brc[1]-blc[1], brc[2]-blc[2] ] N = crossproduct(u,v) N = normalize(N) # calculate feet of perpendiculars feet_points = [foot(crv_points[i], ulc, N) for i in range(len(crv_points))] ####################################################################################### # create a list of 0.1m squares that partition the whole wall surface # !!! it is assumed that the wall surface is a rectangle # !!! three of whose vertices are ulc, blc and brc (and the fourth one is ulc+brc-blc) ####################################################################################### # a new orthonormal system for the wall surface u = normalize(u) v = crossproduct(N,u) v = normalize(v) # transform feet_point coordinates to the uv system # since N, u, v is an orthonormal system we have that # for each vector X = <X,N>N + <X,u>u + <X,v>v # this will be applied to vectors feet_points-ulc which belong to the wall surface plane feet_points_uv = [ [dotproduct(subtract(fp, ulc), u), dotproduct(subtract(fp, ulc), v)] for fp in feet_points] # form a list of squares and a list of their centers in uv coordinates squaresize = 0.1 maxi = int(length(subtract(blc, ulc))/squaresize)-1 maxj = int(length(subtract(brc, blc))/squaresize)-1 squarelist = [ [ [ ((i+0.5)*squaresize, (j+0.5)*squaresize), ((i+1.5)*squaresize, (j+0.5)*squaresize), ((i+1.5)*squaresize, (j+1.5)*squaresize), ((i+0.5)*squaresize, (j+1.5)*squaresize) ] for j in range(maxj) ] for i in range(maxi)] squarecenters = [ ( (i+1)*squaresize, (j+1)*squaresize ) for i in range(maxi) for j in range(maxj) ] # for each square check whether its center belongs to the polygon defined by NURBS curve points import matplotlib.path as mplPath path = mplPath.Path(feet_points_uv) inside = path.contains_points(squarecenters) # select only those squares whose centers are inside the NURBS curve insideindices = [ [ j for j in range(maxj) if inside[i*maxj+j] ] for i in range(maxi) ] # now insideindices[i] contains all j such that squarelist[i][j] is inside a NURBS curve ################################################################################# # create string of idf definitions for rectangles that approximate NURBS opening ################################################################################# idf_total_opening_def = "" for i in range(maxi): # go through all inside squares within i-th column, if there are any if len(insideindices[i])>0: # pn and kn contain the beginning and the end of # subsequences of consecutive numbers within the insideindices[i] list pn = insideindices[i][0] kn = insideindices[i][0] for k in range(1, len(insideindices[i])+1): if k<len(insideindices[i]) and insideindices[i][k]==insideindices[i][k-1]+1: # consecutive subsequence goes on kn = insideindices[i][k] else: # consecutive subsequence had ended, so create an opening element # squarelist[i][pn][0],[1] contain its first two vertices in uv system, # squarelist[i][kn][2],[3] contain its last two vertices in uv system # recalculate vertices in xyz system first vertex1 = [ ulc[0] + squarelist[i][pn][0][0] * u[0] + squarelist[i][pn][0][1] * v[0], ulc[1] + squarelist[i][pn][0][0] * u[1] + squarelist[i][pn][0][1] * v[1], ulc[2] + squarelist[i][pn][0][0] * u[2] + squarelist[i][pn][0][1] * v[2] ] vertex2 = [ ulc[0] + squarelist[i][pn][1][0] * u[0] + squarelist[i][pn][1][1] * v[0], ulc[1] + squarelist[i][pn][1][0] * u[1] + squarelist[i][pn][1][1] * v[1], ulc[2] + squarelist[i][pn][1][0] * u[2] + squarelist[i][pn][1][1] * v[2] ] vertex3 = [ ulc[0] + squarelist[i][kn][2][0] * u[0] + squarelist[i][kn][2][1] * v[0], ulc[1] + squarelist[i][kn][2][0] * u[1] + squarelist[i][kn][2][1] * v[1], ulc[2] + squarelist[i][kn][2][0] * u[2] + squarelist[i][kn][2][1] * v[2] ] vertex4 = [ ulc[0] + squarelist[i][kn][3][0] * u[0] + squarelist[i][kn][3][1] * v[0], ulc[1] + squarelist[i][kn][3][0] * u[1] + squarelist[i][kn][3][1] * v[1], ulc[2] + squarelist[i][kn][3][0] * u[2] + squarelist[i][kn][3][1] * v[2] ] vert_str = "{:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}".format( vertex1[0], vertex1[1], vertex1[2], vertex2[0], vertex2[1], vertex2[2], vertex3[0], vertex3[1], vertex3[2], vertex4[0], vertex4[1], vertex4[2]) countervert_str = "{:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}, {:f}".format( vertex1[0], vertex1[1], vertex1[2], vertex4[0], vertex4[1], vertex4[2], vertex3[0], vertex3[1], vertex3[2], vertex2[0], vertex2[1], vertex2[2]) # fill out the entries in the opening string definition single_opening_def = opening_str.replace('<IDX>', str(i)+'_'+str(pn)).replace('<BASESURFACE>', base_surface).replace('<VERTICES>', vert_str).replace('<COUNTERVERTICES>', countervert_str) idf_total_opening_def = idf_total_opening_def + single_opening_def # a new consecutive subsequence has just begun provided that k<len(insideindices[i]) if k<len(insideindices[i]): pn = insideindices[i][k] kn = insideindices[i][k] # create idf opening objects from the string containing opening definitions from io import StringIO idf_opening = IDF(StringIO(idf_total_opening_def)) # copy idf shading objects to the existing idf file openings = idf_opening.idfobjects["FENESTRATIONSURFACE:DETAILED"] for opening in openings: idf_collection.copyidfobject(opening) ############################### # at the end, save the changes ############################### idf_collection.save()