def __init__(self, base_dir_path, simulation_name=None): """ Parameters ---------- base_dir_path: simulation dir path simulation_name: str, default None if provided, simulation will be looked for in {base_dir_path}/{simulation_name} else, simulation will be looked for in {base_dir_path} A simulation is not characterized by it's input files but by it's base_dir_path. This approach makes it possible to load an already simulated directory without having to define it's idf or epw. """ # store absolute: important for eplus commands self._dir_abs_path = os.path.abspath( self.get_simulation_dir_path(base_dir_path, simulation_name=simulation_name)) # check directory exists if not os.path.isdir(self._dir_abs_path): raise NotADirectoryError( f"simulation directory not found: {self._dir_abs_path}") # update resource map self._update_resource_map() # check info file exists, create it if not if self.get_resource_path(ResourcesRefs.info) is None: logger.warning( "Info file not found (#info.json), creating one. " "This can happen if simulation was not created by oplus.") # find idf idf_path = self.get_resource_path(ResourcesRefs.idf) if idf_path is None: raise FileNotFoundError( "Idf file not found, can't create simulation object.") # find epm version epm = Epm.load(idf_path) eplus_version = _get_eplus_version(epm) # find simulation status (we can't use get_resource_rel_path because no _info variable yet) err_path = self.get_resource_path(ResourcesRefs.err) if err_path is None: status = EMPTY else: err_path = os.path.join(self._dir_abs_path, err_path) status = _get_done_simulation_status(err_path) # create and dump info info = Info(status=status, eplus_version=eplus_version) info.to_json( get_opyplus_path(self._dir_abs_path, ResourcesRefs.info)) # reload map self._update_resource_map() # load info file self._load_info()
def setUpClass(cls): cls.epms_d = {} for eplus_version in TESTED_EPLUS_VERSIONS: cls.epms_d[eplus_version] = Epm.load(os.path.join( get_eplus_base_dir_path(eplus_version), "ExampleFiles", "1ZoneEvapCooler.idf"), idd_or_version=eplus_version)
def test_multiple_branch_links(self): for _ in iter_eplus_versions(self): idf = Epm( os.path.join(CONF.eplus_base_dir_path, "ExampleFiles", "5ZoneAirCooled.idf")) bl = idf.BranchList.one( lambda x: x.name == "heating supply side branches") b3 = idf.Branch.one( lambda x: x.name == "heating supply bypass branch") self.assertEqual(bl[3], b3)
def setUpClass(cls): cls.epms_d = {} for eplus_version in TESTED_EPLUS_VERSIONS: CONF.eplus_version = eplus_version cls.epms_d[eplus_version] = Epm.from_idf(os.path.join( CONF.eplus_base_dir_path, "ExampleFiles", "1ZoneEvapCooler.idf") )
def generate_outputs(): for eplus_version in TESTED_EPLUS_VERSIONS: # set eplus version CONF.eplus_version = eplus_version # iter simulation cases for simulation_case in to_simulate: # building_dir_name building_dir_name = simulation_case["dir_name"] # prepare base dir building_path = os.path.realpath( os.path.join(os.path.dirname(__file__), "..", "simulations-outputs", building_dir_name)) if not os.path.isdir(building_path): os.mkdir(building_path) # prepare directory name (or skip if exists) eplus_version_str = "-".join([str(v) for v in eplus_version]) dir_path = os.path.join(building_path, eplus_version_str) if os.path.isdir(dir_path): continue os.mkdir(dir_path) # set paths idf_path = os.path.join(CONF.eplus_base_dir_path, "ExampleFiles", f"{simulation_case['idf']}.idf") epw_path = os.path.join(CONF.eplus_base_dir_path, "WeatherData", f"{simulation_case['epw']}.epw") # prepare idf if needed pre_process = simulation_case.get("pre_process") if pre_process is not None: idf = Epm.from_idf(idf_path) pre_process(idf) else: idf = idf_path # inform user print(eplus_version) print(idf_path) print(epw_path) print("---") # simulate simulate(idf, epw_path, dir_path) # remove unwanted extensions for file_name in os.listdir(dir_path): file_path = os.path.join(dir_path, file_name) _, ext = os.path.splitext(file_path) if ext[1:] not in simulation_case["extensions"]: os.remove(file_path)
def test_summary_table(self): for eplus_version in iter_eplus_versions(self): base_dir_path = get_eplus_base_dir_path(eplus_version) idf_path = os.path.join(base_dir_path, "ExampleFiles", "4ZoneWithShading_Simple_1.idf") epw_path = os.path.join(base_dir_path, "WeatherData", "USA_CO_Golden-NREL.724666_TMY3.epw") with tempfile.TemporaryDirectory() as temp_dir_path: idf = Epm.load(idf_path) idf.OutputControl_Table_Style.add({0: "Comma", 1: "JtoKWH"}) idf.Output_Table_SummaryReports.add({0: "AllSummary"}) s = simulate(idf, epw_path, temp_dir_path) self.assertIsNotNone(s.get_out_summary_table())
def generate_outputs(): for eplus_version in TESTED_EPLUS_VERSIONS: # iter simulation cases for simulation_case in to_simulate: # building_dir_name building_dir_name = simulation_case["dir_name"] # prepare base dir building_path = getattr(Resources.SimulationsOutputs, building_dir_name) if not os.path.isdir(building_path): os.mkdir(building_path) # prepare directory name (or skip if exists) eplus_version_str = "-".join([str(v) for v in eplus_version]) dir_path = os.path.join(building_path, eplus_version_str) if os.path.isdir(dir_path): continue os.mkdir(dir_path) # set paths idf_path = os.path.join(get_eplus_base_dir_path(eplus_version), "ExampleFiles", f"{simulation_case['idf']}.idf") epw_path = os.path.join(get_eplus_base_dir_path(eplus_version), "WeatherData", f"{simulation_case['epw']}.epw") # prepare idf if needed pre_process = simulation_case.get("pre_process") if pre_process is not None: idf = Epm.load(idf_path) pre_process(idf) else: idf = idf_path # inform user print(eplus_version) print(idf_path) print(epw_path) print("---") # simulate simulate(idf, epw_path, dir_path) # remove unwanted extensions for file_name in os.listdir(dir_path): if get_resource_ref( file_name) not in simulation_case["keep_resources"]: os.remove(os.path.join(dir_path, file_name))
def test_simulate(self): for eplus_version in iter_eplus_versions(self): # prepare paths idf_path = os.path.join(CONF.eplus_base_dir_path, "ExampleFiles", "1ZoneEvapCooler.idf") epw_path = os.path.join( CONF.eplus_base_dir_path, "WeatherData", "USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.epw") # prepare a quick simulation idf = Epm.from_idf(idf_path) sc = idf.SimulationControl.one() sc.run_simulation_for_sizing_periods = "No" rp = idf.RunPeriod.one() rp.end_month = 1 rp.end_day_of_month = 1 # prepare outputs out_f = io.StringIO() err_f = io.StringIO() # simulate with tempfile.TemporaryDirectory() as dir_path: s = simulate(idf, epw_path, dir_path, stdout=out_f, stderr=err_f, beat_freq=0.1) # check one day output eso_df = s.eso.get_data() self.assertEqual(24, len(eso_df)) # check err (manage differences between eplus versions) err_out = err_f.getvalue() self.assertTrue( (err_out == "") or ("EnergyPlus Completed Successfully.\n" in err_out)) # check beat out_str = out_f.getvalue() self.assertIn("subprocess is still running", out_str) # check stdout out_str = out_str.replace("subprocess is still running\n", "") self.assertGreater(len(out_str.split("\n")), 15) # check that more than 15 lines
def test_simulate(self): for eplus_version in iter_eplus_versions(self): # prepare paths idf_path = os.path.join(get_eplus_base_dir_path(eplus_version), "ExampleFiles", "1ZoneEvapCooler.idf") epw_path = os.path.join( get_eplus_base_dir_path(eplus_version), "WeatherData", "USA_IL_Chicago-OHare.Intl.AP.725300_TMY3.epw") # prepare a quick simulation idf = Epm.load(idf_path) sc = idf.SimulationControl.one() sc.run_simulation_for_sizing_periods = "No" rp = idf.RunPeriod.one() rp.end_month = 1 rp.end_day_of_month = 1 # prepare outputs all_messages = [] def print_fct(message): all_messages.append(message) # simulate with tempfile.TemporaryDirectory() as dir_path: s = simulate(idf, epw_path, dir_path, print_function=print_fct, beat_freq=0.1) # check one day output eso_df = s.get_out_eso().get_data() self.assertEqual(24, len(eso_df)) # aggregate messages complete_message = "\n".join(all_messages) # check subprocess is still running self.assertIn("subprocess is still running", complete_message) # check stdout without_subprocess_message = complete_message.replace( "subprocess is still running\n", "") self.assertGreater(len(without_subprocess_message.split("\n")), 15) # check that more than 15 lines
def run_eplus(epm_or_idf_path, weather_data_or_epw_path, simulation_dir_path, stdout=None, stderr=None, beat_freq=None): """ Parameters ---------- epm_or_idf_path: weather_data_or_epw_path simulation_dir_path stdout: default sys.stdout stderr: default sys.stderr beat_freq: if not none, stdout will be used at least every beat_freq (in seconds) """ # work with absolute paths simulation_dir_path = os.path.abspath(simulation_dir_path) # check dir path if not os.path.isdir(simulation_dir_path): raise NotADirectoryError("Simulation directory does not exist: '%s'." % simulation_dir_path) # epm if not isinstance(epm_or_idf_path, Epm): # we don't copy file directly because we want to manage it's external files # could be optimized (use _copy_without_read_only) epm = Epm.from_idf(epm_or_idf_path) else: epm = epm_or_idf_path # gather external files simulation_idf_path = os.path.join(simulation_dir_path, CONF.simulation_base_name + ".idf") epm.gather_external_files(get_external_files_dir_path(simulation_idf_path)) epm.to_idf(simulation_idf_path) # weather data simulation_epw_path = os.path.join(simulation_dir_path, CONF.simulation_base_name + ".epw") if isinstance(weather_data_or_epw_path, WeatherData): weather_data_or_epw_path.to_epw(simulation_epw_path) else: # no need to load: we copy directly _copy_without_read_only(weather_data_or_epw_path, simulation_epw_path) # copy epw if needed (depends on os/eplus version) temp_epw_path = get_simulated_epw_path() if temp_epw_path is not None: _copy_without_read_only(simulation_epw_path, temp_epw_path) # prepare command eplus_relative_cmd = get_simulation_base_command() eplus_cmd = os.path.join(CONF.eplus_base_dir_path, eplus_relative_cmd) # idf idf_command_style = get_simulation_input_command_style("idf") if idf_command_style == SIMULATION_INPUT_COMMAND_STYLES.simu_dir: idf_file_cmd = os.path.join(simulation_dir_path, CONF.simulation_base_name) elif idf_command_style == SIMULATION_INPUT_COMMAND_STYLES.file_path: idf_file_cmd = simulation_idf_path else: raise AssertionError("should not be here") # epw epw_command_style = get_simulation_input_command_style("epw") if epw_command_style == SIMULATION_INPUT_COMMAND_STYLES.simu_dir: epw_file_cmd = os.path.join(simulation_dir_path, CONF.simulation_base_name) elif epw_command_style == SIMULATION_INPUT_COMMAND_STYLES.file_path: epw_file_cmd = simulation_epw_path else: raise AssertionError("should not be here") # command list simulation_command_style = get_simulation_command_style() if simulation_command_style == SIMULATION_COMMAND_STYLES.args: cmd_l = [eplus_cmd, idf_file_cmd, epw_file_cmd] elif simulation_command_style == SIMULATION_COMMAND_STYLES.kwargs: cmd_l = [eplus_cmd, "-w", epw_file_cmd, "-r", idf_file_cmd] else: raise RuntimeError("should not be here") # launch calculation run_subprocess(cmd_l, cwd=simulation_dir_path, stdout=stdout, stderr=stderr, beat_freq=beat_freq) # if needed, we delete temp weather data (only on Windows, see above) if (temp_epw_path is not None) and os.path.isfile(temp_epw_path): os.remove(os.path.join(temp_epw_path))
def get_out_epm(self): return Epm.load( self.get_resource_path(ResourcesRefs.idf, raise_if_not_found=True))
def get_in_epm(self): return Epm.load(self.get_resource_path(ResourcesRefs.idf))
def from_inputs(cls, base_dir_path, epm_or_buffer_or_path, weather_data_or_buffer_or_path, simulation_name=None): # create dir if needed dir_path = base_dir_path if simulation_name is None else os.path.join( base_dir_path, simulation_name) if not os.path.isdir(dir_path): os.mkdir(dir_path) # check empty if len(os.listdir(dir_path)) > 0: logger.warning( f"called Simulation.from_input on a simulation directory that is not empty ({dir_path})" ) # epm epm_path_was_given = False if isinstance(epm_or_buffer_or_path, Epm): epm = epm_or_buffer_or_path else: if isinstance(epm_or_buffer_or_path, str) and os.path.isfile(epm_or_buffer_or_path): epm_path_was_given = True epm = Epm.load( epm_or_buffer_or_path ) # we load epm (even if we will copy input file) to read e+ version # weather data weather_data, weather_data_path_was_given = None, False if isinstance(weather_data_or_buffer_or_path, WeatherData): weather_data = weather_data_or_buffer_or_path elif isinstance( weather_data_or_buffer_or_path, str) and os.path.isfile(weather_data_or_buffer_or_path): weather_data_path_was_given = True else: weather_data = WeatherData.load(weather_data_or_buffer_or_path) # find eplus version eplus_version = _get_eplus_version(epm) # store simulation inputs # idf simulation_epm_path = get_opyplus_path(dir_path, ResourcesRefs.idf) if epm_path_was_given: shutil.copy2(epm_or_buffer_or_path, simulation_epm_path) else: epm.save(simulation_epm_path) # epw simulation_weather_data_path = get_opyplus_path( dir_path, ResourcesRefs.epw) if weather_data_path_was_given: shutil.copy2(weather_data_or_buffer_or_path, simulation_weather_data_path) else: weather_data.save(simulation_weather_data_path) # store info info = Info(EMPTY, eplus_version) info.to_json(get_opyplus_path(dir_path, ResourcesRefs.info)) # create and return simulation return cls(base_dir_path, simulation_name=simulation_name)
def test_simple_read(self): for _ in iter_eplus_versions(self): for idf_name in ("4ZoneWithShading_Simple_1", ): Epm( os.path.join(CONF.eplus_base_dir_path, "ExampleFiles", f"{idf_name}.idf"))
import os import tempfile from oplus.configuration import CONF from oplus import Epm idf = Epm( os.path.join(CONF.eplus_base_dir_path, "ExampleFiles", "1ZoneEvapCooler.idf")) zone = idf["Zone"].one(lambda x: x["name"] == "Main Zone") building = idf["Building"].one(lambda x: x["name"] == "Bldg") # check info if True: print(idf.get_info(sort_by_group=False, detailed=True)) if True: print(zone.get_info(detailed=False)) # check to_str if True: zone.set_head_comment("Hello\n\n\nhello!!") zone.set_tail_comment( "Here is my tail comment\nwritten on several lines...") zone.set_field_comment( 0, zone.get_field_comment(0) + " **modified with\nline\nbreaks**") print(zone.to_idf(style="console")) # idf, console # check save_as if True:
def get_idf(): return Epm(os.path.join(CONF.eplus_base_dir_path, "ExampleFiles", "1ZoneEvapCooler.idf"))