def main(self, run_directory, file_name, args): self.callback("In SiteLocationWorkflow.main(), about to process file") file_path = os.path.join(run_directory, file_name) content = open(file_path).read() new_lines = [] for line in content.split('\n'): if line.strip() == '': continue if '!' not in line: new_lines.append(line.strip()) else: line_without_comment = line[0:line.index('!')].strip() if line_without_comment != '': new_lines.append(line_without_comment) one_long_line = ''.join(new_lines) objects = one_long_line.split(';') for obj in objects: if obj.upper().startswith('SITE:LOCATION'): location_fields = obj.split(',') location_name = location_fields[1] break else: return EPLaunchWorkflowResponse1( success=False, message='Could not parse location object!', column_data={ColumnNames.Location: '*unknown*'}) self.callback("Completed SiteLocationWorkflow.main()") return EPLaunchWorkflowResponse1( success=True, message='Parsed Location object successfully', column_data={ColumnNames.Location: location_name})
def main(self, run_directory, file_name, args): print(args['workflow location']) self.versionclass = Version() if 'workflow location' in args: self.transition_executable_files = self.find_transition_executable_files( args['workflow location']) if self.transition_executable_files: print(self.transition_executable_files) full_file_path = os.path.join(run_directory, file_name) if os.path.exists(full_file_path): returned_success, returned_message = self.perform_transition( full_file_path) return EPLaunchWorkflowResponse1(success=returned_success, message=returned_message, column_data=[]) else: return EPLaunchWorkflowResponse1( success=False, message="Transition file not found: {}!".format(''), column_data=[]) else: return EPLaunchWorkflowResponse1( success=False, message="Transition exefile not found: {}!".format(''), column_data=[]) else: return EPLaunchWorkflowResponse1( success=False, message="Workflow location missing: {}!".format( args['worflow location']), column_data=[])
def test_proper_construction(self): wfr = EPLaunchWorkflowResponse1(True, 'It is done', {'column1': 'data1'}, extra='data') self.assertTrue(wfr.success) self.assertEqual(wfr.message, 'It is done') self.assertIn('column1', wfr.column_data) self.assertIn('extra', wfr.extra_data)
def main(self, run_directory, file_name, args): response = EPlusRunManager.run_energyplus(self, True, run_directory, file_name, args) if type(response) is not EPLaunchWorkflowResponse1: response = EPLaunchWorkflowResponse1( success=False, message='Current workflow run_energyplus function did not respond properly', column_data=None ) return response
def run(self): """Run Workflow Thread.""" try: workflow_response = self.workflow_instance.main( self.run_directory, self.file_name, self.workflow_main_args) if type(workflow_response) is not EPLaunchWorkflowResponse1: workflow_response = EPLaunchWorkflowResponse1( success=False, message= 'Current workflow main function did not respond properly', column_data=None) except Exception as e: # here is another location where we simply don't know what types of errors could occur in user defined files workflow_response = EPLaunchWorkflowResponse1( success=False, message='Current workflow main function failed unexpectedly:' + str(e), column_data=None) workflow_response.id = self.id r = ResultEvent(workflow_response) try: wx.PostEvent(self._notify_window, r) except RuntimeError: pass
def main(self, run_directory, file_name, args): if 'workflow location' in args: energyplus_root_folder, _ = os.path.split( args['workflow location']) preprocess_folder = os.path.join(energyplus_root_folder, 'PreProcess') coeffconv_folder = os.path.join(preprocess_folder, 'CoeffConv') if platform.system() == 'Windows': coeffconv_binary = os.path.join(coeffconv_folder, 'CoeffConv.exe') else: coeffconv_binary = os.path.join(coeffconv_folder, 'CoeffConv') if not os.path.exists(coeffconv_binary): return EPLaunchWorkflowResponse1( success=False, message="CoeffConv binary not found: {}!".format( coeffconv_binary), column_data=[]) else: return EPLaunchWorkflowResponse1( success=False, message="Workflow location missing: {}!".format( args['worflow location']), column_data=[]) coi_file_with_path = os.path.join(run_directory, file_name) coi_file_no_ext, _ = os.path.splitext(coi_file_with_path) coo_file_with_path = coi_file_no_ext + '.coo' # clean up working directory cc_input_txt_file = os.path.join(run_directory, 'CoeffConvInput.txt') if os.path.exists(cc_input_txt_file): os.remove(cc_input_txt_file) cc_output_txt_file = os.path.join(run_directory, 'CoeffConvOutput.txt') if os.path.exists(cc_output_txt_file): os.remove(cc_output_txt_file) # copy input data file to working directory if os.path.exists(coi_file_with_path) and os.path.exists( coeffconv_binary) and os.path.exists(run_directory): shutil.copy2(coi_file_with_path, cc_input_txt_file) # execute utility command_line_args = [ coeffconv_binary, ] process = subprocess.run( command_line_args, creationflags=subprocess.CREATE_NEW_CONSOLE, cwd=run_directory) if process.returncode == 0: # Remove old version of the output file if os.path.exists(coo_file_with_path): os.remove(coo_file_with_path) # Copy output files to input/output path shutil.copy2(cc_output_txt_file, coo_file_with_path) # Clean up directory. if os.path.exists(cc_input_txt_file): os.remove(cc_input_txt_file) if os.path.exists(cc_output_txt_file): os.remove(cc_output_txt_file) return EPLaunchWorkflowResponse1( success=True, message="Ran CoeffConv OK for file: {}!".format( coi_file_with_path), column_data=[]) else: return EPLaunchWorkflowResponse1( success=False, message="CoeffConv failed for file: {}!".format( coi_file_with_path), column_data=[]) else: return EPLaunchWorkflowResponse1( success=False, message="CoeffConv file not found: {}!".format( coi_file_with_path), column_data=[])
def main(self, run_directory, file_name, args): if 'workflow location' in args: energyplus_root_folder, _ = os.path.split( args['workflow location']) postprocess_folder = os.path.join(energyplus_root_folder, 'PostProcess') appgpp_folder = os.path.join(postprocess_folder, 'AppGPostProcess') if platform.system() == 'Windows': appgpp_binary = os.path.join(appgpp_folder, 'appgpostprocess.exe') else: appgpp_binary = os.path.join(appgpp_folder, 'appgpostprocess') if not os.path.exists(appgpp_binary): return EPLaunchWorkflowResponse1( success=False, message="AppGPostProcess binary not found: {}!".format( appgpp_binary), column_data=[]) else: return EPLaunchWorkflowResponse1( success=False, message="Workflow location missing: {}!".format( args['worflow location']), column_data=[]) html_in_file_with_path = os.path.join(run_directory, file_name) html_in_file_no_ext, _ = os.path.splitext(html_in_file_with_path) if html_in_file_no_ext[-10:] != '-G000Table': return EPLaunchWorkflowResponse1( success=False, message='A file ending in -G000Table.html must be selected', column_data=[]) # else: # out_file_root = html_in_file_no_ext[:-10] + '-GAVG' # html_out_file = out_file_root + 'Table.html' # csv_out_file = out_file_root + '.csv' # csvmeter_out_file = out_file_root + 'Meter.csv' # copy input data file to working directory if os.path.exists(html_in_file_with_path) and os.path.exists( appgpp_binary) and os.path.exists(run_directory): # execute utility command_line_args = [appgpp_binary, html_in_file_with_path] process = subprocess.run( command_line_args, creationflags=subprocess.CREATE_NEW_CONSOLE, cwd=run_directory) if process.returncode == 0: return EPLaunchWorkflowResponse1( success=True, message="Ran AppendixGPostProcess OK for file: {}!".format( html_in_file_with_path), column_data=[]) else: return EPLaunchWorkflowResponse1( success=False, message="AppendixGPostProcess failed for file: {}!".format( html_in_file_with_path), column_data=[]) else: return EPLaunchWorkflowResponse1( success=False, message="AppendixGPostProcess files not found", column_data=[])
def main(self, run_directory, file_name, args): if 'workflow location' in args: energyplus_root_folder, _ = os.path.split( args['workflow location']) preprocess_folder = os.path.join(energyplus_root_folder, 'PreProcess') calc_soil_surf_temp_folder = os.path.join(preprocess_folder, 'CalcSoilSurfTemp') if platform.system() == 'Windows': calc_soil_surf_temp_binary = os.path.join( calc_soil_surf_temp_folder, 'CalcSoilSurfTemp.exe') else: calc_soil_surf_temp_binary = os.path.join( calc_soil_surf_temp_folder, 'CalcSoilSurfTemp') if not os.path.exists(calc_soil_surf_temp_binary): return EPLaunchWorkflowResponse1( success=False, message="CalcSoilSurfTemp binary not found: {}!".format( calc_soil_surf_temp_binary), column_data=[]) else: return EPLaunchWorkflowResponse1( success=False, message="Workflow location missing: {}!".format( args['worflow location']), column_data=[]) full_file_path = os.path.join(run_directory, file_name) full_file_no_ext, _ = os.path.splitext(full_file_path) out_file_path = full_file_no_ext + '.out' csst_out = os.path.join(run_directory, 'CalcSoilSurfTemp.out') if os.path.exists(csst_out): self.callback("Removing previous output file") os.remove(csst_out) if os.path.exists(out_file_path): try: os.remove(out_file_path) except OSError: return EPLaunchWorkflowResponse1( success=False, message= "Could not delete prior CalcSoilSurfTemp results file: %s!" % out_file_path, column_data={}) # run E+ and gather (for now fake) data self.callback("Running CalcSoilSurfTemp!") p1 = Popen([calc_soil_surf_temp_binary, file_name], stdout=PIPE, stdin=PIPE, cwd=run_directory) p1.communicate(input=b'1\n1\n') self.callback("CalcSoilSurfTemp Completed!") if not os.path.exists(csst_out): return EPLaunchWorkflowResponse1( success=False, message="CalcSoilSurfTemp failed for file: %s!" % full_file_path, column_data={}) if os.path.exists(out_file_path): os.remove(out_file_path) # Copy output files to input/output path shutil.copy2(csst_out, out_file_path) # Clean up directory. if os.path.exists(csst_out): os.remove(csst_out) try: self.callback("Processing output file...") with open(out_file_path, 'r') as f: lines = f.readlines() avg_temp = float(lines[1][40:-1]) amp_temp = float(lines[2][38:-1]) phase_constant = int(lines[3][42:-1]) column_data = { ColumnNames.AverageSurfTemp: avg_temp, ColumnNames.AmplitudeSurfTemp: amp_temp, ColumnNames.PhaseConstant: phase_constant } self.callback(" ...DONE!") return EPLaunchWorkflowResponse1( success=True, message="Ran EnergyPlus OK for file: %s!" % file_name, column_data=column_data) except Exception: # noqa -- there could be lots of issues here, file existence, file contents, float conversion self.callback(" ...FAILED!") return EPLaunchWorkflowResponse1( success=False, message= "CalcSoilSurfTemp seemed to run, but post processing failed for file: %s!" % full_file_path, column_data={})
def run_energyplus(self, isIP, run_directory, file_name, args): full_file_path = os.path.join(run_directory, file_name) file_name_no_ext, extension = os.path.splitext(file_name) # the following is the same when .idf is used if 'workflow location' in args: energyplus_root_folder, _ = os.path.split( args['workflow location']) # Run EnergyPlus binary if platform.system() == 'Windows': energyplus_binary = os.path.join(energyplus_root_folder, 'energyplus.exe') else: energyplus_binary = os.path.join(energyplus_root_folder, 'energyplus') if not os.path.exists(energyplus_binary): return EPLaunchWorkflowResponse1( success=False, message="EnergyPlus binary not found: {}!".format( energyplus_binary), column_data=[]) else: return EPLaunchWorkflowResponse1( success=False, message="Workflow location missing: {}!".format( args['worflow location']), column_data=[]) v = Version() is_found, current_version, numeric_version = v.check_energyplus_version( full_file_path) if is_found: if numeric_version >= 80300: # EnergyPlus 8.3.0 was the first with command line options. # start with the binary name, obviously command_line_args = [energyplus_binary] if extension == '.imf': command_line_args += ['--epmacro'] if extension != '.epJSON': command_line_args += ['--expandobjects'] if not isIP: # if using SI output units just use readvars CLI option command_line_args += ['--readvars'] # add some config parameters command_line_args += [ '--output-prefix', file_name_no_ext, '--output-suffix', 'C' ] # add in simulation control args if 'weather' in args and args['weather']: command_line_args += ['--weather', args['weather']] else: command_line_args += ['--design-day'] # and at the very end, add the file to run command_line_args += [full_file_path] # run E+ and gather (for now fake) data try: for message in self.execute_for_callback( command_line_args, run_directory): self.callback(message) except subprocess.CalledProcessError: self.callback("E+ FAILED") return EPLaunchWorkflowResponse1( success=False, message="EnergyPlus failed for file: %s!" % full_file_path, column_data={}) if isIP: # set up the ESO and MTR output files for either unit conversion or just ReadVarsESO # *.eso back to eplusout.eso eso_path = os.path.join(run_directory, file_name_no_ext + '.eso') eplusouteso_path = os.path.join(run_directory, 'eplusout.eso') shutil.copy(eso_path, eplusouteso_path) # *.mtr back to eplusout.mtr mtr_path = os.path.join(run_directory, file_name_no_ext + '.mtr') eplusoutmtr_path = os.path.join(run_directory, 'eplusout.mtr') shutil.copy(mtr_path, eplusoutmtr_path) # run the ConvertESOMTR program to create IP versions of the timestep based output files if platform.system() == 'Windows': convertESOMTR_binary = os.path.join( energyplus_root_folder, 'PostProcess', 'convertESOMTRpgm', 'convertESOMTR.exe') else: convertESOMTR_binary = os.path.join( energyplus_root_folder, 'PostProcess', 'convertESOMTRpgm', 'convertESOMTR') if os.path.exists(convertESOMTR_binary): converttxt_orig_path = os.path.join( energyplus_root_folder, 'PostProcess', 'convertESOMTRpgm', 'convert.txt') converttxt_run_path = os.path.join( run_directory, 'convert.txt') shutil.copy(converttxt_orig_path, converttxt_run_path) command_line_args = [convertESOMTR_binary] try: for message in self.execute_for_callback( command_line_args, run_directory): self.callback(message) except subprocess.CalledProcessError: self.callback("ConvertESOMTR FAILED") return EPLaunchWorkflowResponse1( success=False, message="ConvertESOMTR failed for file: %s!" % full_file_path, column_data={}) # copy converted IP version of ESO file to users *.eso file ipeso_path = os.path.join(run_directory, 'ip.eso') if os.path.exists(ipeso_path): shutil.copy(ipeso_path, eso_path) os.replace(ipeso_path, eplusouteso_path) # copy converted IP version of MTR file to users *.mtr file ipmtr_path = os.path.join(run_directory, 'ip.mtr') if os.path.exists(ipmtr_path): shutil.copy(ipmtr_path, mtr_path) os.replace(ipmtr_path, eplusoutmtr_path) os.remove(converttxt_run_path) # run ReadVarsESO to convert the timestep based output files to CSV files if platform.system() == 'Windows': readvarseso_binary = os.path.join( energyplus_root_folder, 'PostProcess', 'ReadVarsESO.exe') else: readvarseso_binary = os.path.join( energyplus_root_folder, 'PostProcess', 'ReadVarsESO') if os.path.exists(readvarseso_binary): command_line_args = [readvarseso_binary] rvi_path = os.path.join(run_directory, file_name_no_ext + '.rvi') eplusout_rvi_path = os.path.join( run_directory, 'eplusout.rvi') if os.path.exists(rvi_path): shutil.copy(rvi_path, eplusout_rvi_path) command_line_args.append('eplusout.rvi') else: command_line_args.append(' ') command_line_args.append( 'unlimited') # no number of column limit try: for message in self.execute_for_callback( command_line_args, run_directory): self.callback(message) except subprocess.CalledProcessError: self.callback("ReadVarsESO FAILED on ESO file") return EPLaunchWorkflowResponse1( success=False, message="ReadVarsESO failed for ESO file: %s!" % full_file_path, column_data={}) vari_csv_path = os.path.join(run_directory, file_name_no_ext + '.csv') eplusout_csv_path = os.path.join( run_directory, 'eplusout.csv') if os.path.exists(eplusout_csv_path): os.replace(eplusout_csv_path, vari_csv_path) command_line_args = [readvarseso_binary] mvi_path = os.path.join(run_directory, file_name_no_ext + '.mvi') temp_mvi_path = os.path.join(run_directory, 'temp.mvi') eplusout_mvi_path = os.path.join( run_directory, 'eplusout.mvi') if os.path.exists(mvi_path): shutil.copy(mvi_path, eplusout_mvi_path) command_line_args.append('eplusout.mvi') else: f = open(temp_mvi_path, "w+") f.write('eplusout.mtr') f.write('eplusmtr.csv') f.close() command_line_args.append('temp.mvi') command_line_args.append( 'unlimited') # no number of column limit try: for message in self.execute_for_callback( command_line_args, run_directory): self.callback(message) except subprocess.CalledProcessError: self.callback("ReadVarsESO FAILED on MTR file") return EPLaunchWorkflowResponse1( success=False, message="ReadVarsESO failed for MTR file: %s!" % full_file_path, column_data={}) mtr_csv_path = os.path.join( run_directory, file_name_no_ext + 'Meter.csv') eplusmtr_csv_path = os.path.join( run_directory, 'eplusmtr.csv') if os.path.exists(eplusmtr_csv_path): os.replace(eplusmtr_csv_path, mtr_csv_path) readvars_audit_path = os.path.join( run_directory, 'readvars.audit') rv_audit_path = os.path.join( run_directory, file_name_no_ext + '.rvaudit') if os.path.exists(readvars_audit_path): os.replace(readvars_audit_path, rv_audit_path) # clean up if os.path.exists(temp_mvi_path): os.remove(temp_mvi_path) if os.path.exists(eplusouteso_path): os.remove(eplusouteso_path) if os.path.exists(eplusoutmtr_path): os.remove(eplusoutmtr_path) if os.path.exists(eplusout_rvi_path): os.remove(eplusout_rvi_path) if os.path.exists(eplusout_mvi_path): os.remove(eplusout_mvi_path) audit_out_path = os.path.join(run_directory, 'audit.out') if os.path.exists(audit_out_path): os.remove(audit_out_path) expanded_idf_path = os.path.join(run_directory, 'expanded.idf') if os.path.exists(expanded_idf_path): os.remove(expanded_idf_path) out_idf_path = os.path.join(run_directory, 'out.idf') if os.path.exists(out_idf_path): os.remove(out_idf_path) # run HVAC-Diagram if platform.system() == 'Windows': hvac_diagram_binary = os.path.join(energyplus_root_folder, 'PostProcess', 'HVAC-Diagram.exe') else: hvac_diagram_binary = os.path.join(energyplus_root_folder, 'PostProcess', 'HVAC-Diagram') if os.path.exists(hvac_diagram_binary): bnd_path = os.path.join(run_directory, file_name_no_ext + '.bnd') eplusout_bnd_path = os.path.join(run_directory, 'eplusout.bnd') if os.path.exists(bnd_path): shutil.copy(bnd_path, eplusout_bnd_path) command_line_args = [hvac_diagram_binary] try: for message in self.execute_for_callback( command_line_args, run_directory): self.callback(message) except subprocess.CalledProcessError: self.callback("HVAC-Diagram FAILED on BND file") return EPLaunchWorkflowResponse1( success=False, message="HVAC-Diagram failed for BND file: %s!" % full_file_path, column_data={}) svg_path = os.path.join(run_directory, file_name_no_ext + '.svg') eplusout_svg_path = os.path.join(run_directory, 'eplusout.svg') if os.path.exists(eplusout_svg_path): os.replace(eplusout_svg_path, svg_path) if os.path.exists(eplusout_bnd_path): os.remove(eplusout_bnd_path) # check on .end file and finish up end_file_name = "{0}.end".format(file_name_no_ext) end_file_path = os.path.join(run_directory, end_file_name) success, errors, warnings, runtime = EPlusRunManager.get_end_summary( end_file_path) column_data = { ColumnNames.Errors: errors, ColumnNames.Warnings: warnings, ColumnNames.Runtime: runtime, ColumnNames.Version: current_version } # now leave return EPLaunchWorkflowResponse1( success=True, message="Ran EnergyPlus OK for file: %s!" % file_name, column_data=column_data) else: errors = "wrong version" column_data = { ColumnNames.Errors: errors, ColumnNames.Warnings: '', ColumnNames.Runtime: 0, ColumnNames.Version: current_version } # now leave return EPLaunchWorkflowResponse1( success=False, message="Incorrect Version found {}: {}!".format( current_version, file_name), column_data=column_data) else: errors = "wrong version" column_data = { ColumnNames.Errors: errors, ColumnNames.Warnings: '', ColumnNames.Runtime: 0, ColumnNames.Version: current_version } # now leave return EPLaunchWorkflowResponse1( success=False, message="Incorrect Version found {}: {}!".format( current_version, file_name), column_data=column_data)
def main(self, run_directory, file_name, args): if 'workflow location' in args: energyplus_root_folder, _ = os.path.split( args['workflow location']) if platform.system() == 'Windows': convertinputformat_binary = os.path.join( energyplus_root_folder, 'ConvertInputFormat.exe') else: convertinputformat_binary = os.path.join( energyplus_root_folder, 'ConvertInputFormat') if not os.path.exists(convertinputformat_binary): return EPLaunchWorkflowResponse1( success=False, message="ConvertInputFormat binary not found: {}!".format( convertinputformat_binary), column_data=[]) else: return EPLaunchWorkflowResponse1( success=False, message="Workflow location missing: {}!".format( args['worflow location']), column_data=[]) original_with_path = os.path.join(run_directory, file_name) converted_file_no_ext, original_ext = os.path.splitext( original_with_path) if original_ext.lower() == '.idf': converted_file_with_path = converted_file_no_ext + '.epJSON' elif original_ext.lower() == '.epjson': converted_file_with_path = converted_file_no_ext + '.idf' else: return EPLaunchWorkflowResponse1( success=False, message="Invalid extension {} on file: {}!".format( original_ext, original_with_path), column_data=[]) if os.path.exists(original_with_path) and os.path.exists( convertinputformat_binary) and os.path.exists(run_directory): # execute utility command_line_args = [convertinputformat_binary, original_with_path] try: for message in self.execute_for_callback( command_line_args, run_directory): self.callback(message) except subprocess.CalledProcessError: self.callback("ConvertInputFormat FAILED") return EPLaunchWorkflowResponse1( success=False, message="ConvertInputFormat failed for file: %s!" % original_with_path, column_data={}) return EPLaunchWorkflowResponse1( success=True, message="Ran ConvertInputFormat OK for file: {}!".format( original_with_path), column_data=[]) else: return EPLaunchWorkflowResponse1( success=False, message="ConvertInputFormat file not found: {}!".format( original_with_path), column_data=[])
def run_energyplus(self, isIP, run_directory, file_name, args, by_api): full_file_path = os.path.join(run_directory, file_name) file_name_no_ext, extension = os.path.splitext(file_name) # the following is the same when .idf is used if 'workflow location' in args: energyplus_root_folder, _ = os.path.split( args['workflow location']) # Run EnergyPlus binary if platform.system() == 'Windows': energyplus_binary = os.path.join(energyplus_root_folder, 'energyplus.exe') else: energyplus_binary = os.path.join(energyplus_root_folder, 'energyplus') if not os.path.exists(energyplus_binary): return EPLaunchWorkflowResponse1( success=False, message="EnergyPlus binary not found: {}!".format( energyplus_binary), column_data=[]) else: return EPLaunchWorkflowResponse1( success=False, message="Workflow location missing: {}!".format( args['workflow location']), column_data=[]) v = Version() is_found, current_version, numeric_version = v.check_energyplus_version( full_file_path) if is_found: if by_api: # if calling through API, then the arguments don't include the E+ binary command_line_args = [] else: command_line_args = [energyplus_binary] if extension == '.imf': command_line_args += ['--epmacro'] # should be able to do this once we get pyExpandObjects going if extension != '.epJSON': command_line_args += ['--expandobjects'] # TODO: add -d run_directory support to the E+ call here # if not isIP: # if using SI output units just use readvars CLI option # command_line_args += ['--readvars'] # add some config parameters command_line_args += [ '--output-prefix', file_name_no_ext, '--output-suffix', 'C' ] # add in simulation control args if 'weather' in args and args['weather']: command_line_args += ['--weather', args['weather']] else: command_line_args += ['--design-day'] # and at the very end, add the file to run command_line_args += [full_file_path] # run E+ if by_api: # if by API then find the API wrapper relative to this workflow, import it, set up a callback, and run eplus_dir = Path(__file__).parent.parent.absolute() sys.path.insert(0, str(eplus_dir)) from pyenergyplus.api import EnergyPlusAPI x = lambda msg: self.callback("API Callback: " + str(msg)) api = EnergyPlusAPI() state = api.state_manager.new_state() api.runtime.callback_message(state, x) api.runtime.set_console_output_status(state, False) cur_dir = os.getcwd() os.chdir(run_directory) eplus_return = api.runtime.run_energyplus( state, command_line_args) os.chdir(cur_dir) if eplus_return != 0: self.callback("E+ FAILED") return EPLaunchWorkflowResponse1( success=False, message="EnergyPlus failed for file: %s!" % full_file_path, column_data={}) else: # if by CLI then just execute the full command line try: for message in self.execute_for_callback( command_line_args, run_directory): self.callback(message) except subprocess.CalledProcessError: self.callback("E+ FAILED") return EPLaunchWorkflowResponse1( success=False, message="EnergyPlus failed for file: %s!" % full_file_path, column_data={}) # if isIP: # set up the ESO and MTR output files for either unit conversion or just ReadVarsESO # *.eso back to eplusout.eso eso_path = os.path.join(run_directory, file_name_no_ext + '.eso') eplusouteso_path = os.path.join(run_directory, 'eplusout.eso') if os.path.exists(eso_path): shutil.copy(eso_path, eplusouteso_path) # *.mtr back to eplusout.mtr mtr_path = os.path.join(run_directory, file_name_no_ext + '.mtr') eplusoutmtr_path = os.path.join(run_directory, 'eplusout.mtr') if os.path.exists(mtr_path): shutil.copy(mtr_path, eplusoutmtr_path) if isIP: # run the ConvertESOMTR program to create IP versions of the timestep based output files if platform.system() == 'Windows': convertESOMTR_binary = os.path.join( energyplus_root_folder, 'PostProcess', 'convertESOMTRpgm', 'convertESOMTR.exe') else: convertESOMTR_binary = os.path.join( energyplus_root_folder, 'PostProcess', 'convertESOMTRpgm', 'convertESOMTR') if os.path.exists(convertESOMTR_binary): converttxt_orig_path = os.path.join( energyplus_root_folder, 'PostProcess', 'convertESOMTRpgm', 'convert.txt') converttxt_run_path = os.path.join(run_directory, 'convert.txt') shutil.copy(converttxt_orig_path, converttxt_run_path) command_line_args = [convertESOMTR_binary] try: for message in self.execute_for_callback( command_line_args, run_directory): self.callback(message) except subprocess.CalledProcessError: self.callback("ConvertESOMTR FAILED") return EPLaunchWorkflowResponse1( success=False, message="ConvertESOMTR failed for file: %s!" % full_file_path, column_data={}) # copy converted IP version of ESO file to users *.eso file ipeso_path = os.path.join(run_directory, 'ip.eso') if os.path.exists(ipeso_path): shutil.copy(ipeso_path, eso_path) os.replace(ipeso_path, eplusouteso_path) # copy converted IP version of MTR file to users *.mtr file ipmtr_path = os.path.join(run_directory, 'ip.mtr') if os.path.exists(ipmtr_path): shutil.copy(ipmtr_path, mtr_path) os.replace(ipmtr_path, eplusoutmtr_path) os.remove(converttxt_run_path) # run ReadVarsESO to convert the timestep based output files to CSV files if platform.system() == 'Windows': readvarseso_binary = os.path.join(energyplus_root_folder, 'PostProcess', 'ReadVarsESO.exe') else: readvarseso_binary = os.path.join(energyplus_root_folder, 'PostProcess', 'ReadVarsESO') if os.path.exists(readvarseso_binary): command_line_args = [readvarseso_binary] rvi_path = os.path.join(run_directory, file_name_no_ext + '.rvi') temp_rvi_path = os.path.join(run_directory, 'temp.rvi') eplusout_rvi_path = os.path.join(run_directory, 'eplusout.rvi') if os.path.exists(rvi_path): shutil.copy(rvi_path, eplusout_rvi_path) command_line_args.append('eplusout.rvi') else: f = open(temp_rvi_path, "w+") f.write('eplusout.eso \n') f.write('eplusout.csv \n') f.close() command_line_args.append('temp.rvi') command_line_args.append( 'unlimited') # no number of column limit try: for message in self.execute_for_callback( command_line_args, run_directory): self.callback(message) except subprocess.CalledProcessError: self.callback("ReadVarsESO FAILED on ESO file") return EPLaunchWorkflowResponse1( success=False, message="ReadVarsESO failed for ESO file: %s!" % full_file_path, column_data={}) vari_csv_path = os.path.join(run_directory, file_name_no_ext + '.csv') eplusout_csv_path = os.path.join(run_directory, 'eplusout.csv') if os.path.exists(eplusout_csv_path): os.replace(eplusout_csv_path, vari_csv_path) command_line_args = [readvarseso_binary] mvi_path = os.path.join(run_directory, file_name_no_ext + '.mvi') temp_mvi_path = os.path.join(run_directory, 'temp.mvi') eplusout_mvi_path = os.path.join(run_directory, 'eplusout.mvi') if os.path.exists(mvi_path): shutil.copy(mvi_path, eplusout_mvi_path) command_line_args.append('eplusout.mvi') else: f = open(temp_mvi_path, "w+") f.write('eplusout.mtr \n') f.write('eplusmtr.csv \n') f.close() command_line_args.append('temp.mvi') command_line_args.append( 'unlimited') # no number of column limit try: for message in self.execute_for_callback( command_line_args, run_directory): self.callback(message) except subprocess.CalledProcessError: self.callback("ReadVarsESO FAILED on MTR file") return EPLaunchWorkflowResponse1( success=False, message="ReadVarsESO failed for MTR file: %s!" % full_file_path, column_data={}) mtr_csv_path = os.path.join(run_directory, file_name_no_ext + 'Meter.csv') eplusmtr_csv_path = os.path.join(run_directory, 'eplusmtr.csv') if os.path.exists(eplusmtr_csv_path): os.replace(eplusmtr_csv_path, mtr_csv_path) readvars_audit_path = os.path.join(run_directory, 'readvars.audit') rv_audit_path = os.path.join(run_directory, file_name_no_ext + '.rvaudit') if os.path.exists(readvars_audit_path): os.replace(readvars_audit_path, rv_audit_path) # clean up things inside this IF block if os.path.exists(temp_rvi_path): os.remove(temp_rvi_path) if os.path.exists(temp_mvi_path): os.remove(temp_mvi_path) if os.path.exists(eplusout_rvi_path): os.remove(eplusout_rvi_path) if os.path.exists(eplusout_mvi_path): os.remove(eplusout_mvi_path) # clean up more things if os.path.exists(eplusouteso_path): os.remove(eplusouteso_path) if os.path.exists(eplusoutmtr_path): os.remove(eplusoutmtr_path) audit_out_path = os.path.join(run_directory, 'audit.out') if os.path.exists(audit_out_path): os.remove(audit_out_path) expanded_idf_path = os.path.join(run_directory, 'expanded.idf') if os.path.exists(expanded_idf_path): os.remove(expanded_idf_path) out_idf_path = os.path.join(run_directory, 'out.idf') if os.path.exists(out_idf_path): os.remove(out_idf_path) # run HVAC-Diagram if platform.system() == 'Windows': hvac_diagram_binary = os.path.join(energyplus_root_folder, 'PostProcess', 'HVAC-Diagram.exe') else: hvac_diagram_binary = os.path.join(energyplus_root_folder, 'PostProcess', 'HVAC-Diagram') if os.path.exists(hvac_diagram_binary): bnd_path = os.path.join(run_directory, file_name_no_ext + '.bnd') eplusout_bnd_path = os.path.join(run_directory, 'eplusout.bnd') if os.path.exists(bnd_path): shutil.copy(bnd_path, eplusout_bnd_path) command_line_args = [hvac_diagram_binary] try: for message in self.execute_for_callback( command_line_args, run_directory): self.callback(message) except subprocess.CalledProcessError: self.callback("HVAC-Diagram FAILED on BND file") return EPLaunchWorkflowResponse1( success=False, message="HVAC-Diagram failed for BND file: %s!" % full_file_path, column_data={}) svg_path = os.path.join(run_directory, file_name_no_ext + '.svg') eplusout_svg_path = os.path.join(run_directory, 'eplusout.svg') if os.path.exists(eplusout_svg_path): os.replace(eplusout_svg_path, svg_path) if os.path.exists(eplusout_bnd_path): os.remove(eplusout_bnd_path) # check on .end file and finish up err_file_name = "{0}.err".format(file_name_no_ext) err_file_path = os.path.join(run_directory, err_file_name) success, errors, warnings, runtime = EPlusRunManager.get_end_summary_from_err( err_file_path) column_data = { ColumnNames.Errors: errors, ColumnNames.Warnings: warnings, ColumnNames.Runtime: runtime, ColumnNames.Version: current_version } # now leave return EPLaunchWorkflowResponse1( success=True, message="Ran EnergyPlus OK for file: %s!" % file_name, column_data=column_data) else: errors = "wrong version" column_data = { ColumnNames.Errors: errors, ColumnNames.Warnings: '', ColumnNames.Runtime: 0, ColumnNames.Version: current_version } # now leave return EPLaunchWorkflowResponse1( success=False, message="Incorrect Version found {}: {}!".format( current_version, file_name), column_data=column_data)
def run_energyplus(self, isIP, run_directory, file_name, args, by_api): full_file_path = os.path.join(run_directory, file_name) file_name_no_ext, extension = os.path.splitext(file_name) output_directory = os.path.join(run_directory, f"EPLaunchRun_{file_name_no_ext}") if os.path.exists(output_directory): shutil.rmtree(output_directory) os.makedirs(output_directory) def delete_if_exists(file_path): if os.path.exists(file_path): os.remove(file_path) if 'workflow location' in args: energyplus_root_folder, _ = os.path.split( args['workflow location']) # Run EnergyPlus binary if platform.system() == 'Windows': energyplus_binary = os.path.join(energyplus_root_folder, 'energyplus.exe') else: energyplus_binary = os.path.join(energyplus_root_folder, 'energyplus') if not os.path.exists(energyplus_binary): return EPLaunchWorkflowResponse1( success=False, message="EnergyPlus binary not found: {}!".format( energyplus_binary), column_data=[]) else: return EPLaunchWorkflowResponse1( success=False, message="Workflow location missing: {}!".format( args['workflow location']), column_data=[]) v = Version() is_found, current_version, numeric_version = v.check_energyplus_version( full_file_path) if not is_found: errors = "wrong version" column_data = { ColumnNames.Errors: errors, ColumnNames.Warnings: '', ColumnNames.Runtime: 0, ColumnNames.Version: current_version } return EPLaunchWorkflowResponse1( success=False, message="Incorrect Version found {}: {}!".format( current_version, file_name), column_data=column_data) if by_api: # if calling through API, then the arguments don't include the E+ binary command_line_args = [] else: command_line_args = [energyplus_binary] if extension == '.imf': command_line_args += ['--epmacro'] # So...ExpandObjects is weird in E+. It doesn't like running things in directories and accidentally symlinks # things into the current working directory even if you specify an output directory # We're just going to run it ourselves. (Side note it could be a similar problem for EPMacro) if extension != '.epJSON': if platform.system() == 'Windows': expand_objects = os.path.join(energyplus_root_folder, 'ExpandObjects.exe') else: expand_objects = os.path.join(energyplus_root_folder, 'ExpandObjects') if not os.path.exists(expand_objects): return EPLaunchWorkflowResponse1( success=False, message="ExpandObjects binary not found: {}!".format( expand_objects), column_data=[]) # go ahead and copy the target IDF and original IDD into the output_dir/in.idf for running ExpandObjects idf_path_in_output_dir = os.path.join(output_directory, 'in.idf') shutil.copy(full_file_path, idf_path_in_output_dir) idd_path = os.path.join( energyplus_root_folder, 'Energy+.idd') # yes for now we still need it idd_path_in_output_dir = os.path.join(output_directory, 'Energy+.idd') shutil.copy(idd_path, idd_path_in_output_dir) # run ExpandObjects try: for message in self.execute_for_callback([expand_objects], output_directory): self.callback(message) except subprocess.CalledProcessError: self.callback("E+ FAILED") return EPLaunchWorkflowResponse1( success=False, message="EnergyPlus failed for file: %s!" % full_file_path, column_data={}) # regardless of what happened, clean up the temp files delete_if_exists(idf_path_in_output_dir) delete_if_exists(idd_path_in_output_dir) # if expanded.idf does not exist then we don't need to do anything, assume it just didn't have any templates # but if it does exist, then this needs to be the IDF that we run, *however* we can't just leave it here # as it may reference some other files back in the original directory. I'm going to go with a new file name # in the original directory of "FileName_Expanded.idf" expanded_path_in_output_dir = os.path.join(output_directory, 'expanded.idf') if os.path.exists(expanded_path_in_output_dir): target_expanded_file_name = os.path.join( run_directory, f"{file_name_no_ext}_Expanded.idf") shutil.copy(expanded_path_in_output_dir, target_expanded_file_name) full_file_path = target_expanded_file_name # Run EnergyPlus in a subdirectory command_line_args += ['-d', output_directory] # if not isIP: # if using SI output units just use readvars CLI option # command_line_args += ['--readvars'] # add some config parameters command_line_args += [ '--output-prefix', file_name_no_ext, '--output-suffix', 'C' ] # add in simulation control args if 'weather' in args and args['weather']: command_line_args += ['--weather', args['weather']] else: command_line_args += ['--design-day'] # and at the very end, add the file to run command_line_args += [full_file_path] # run E+ if by_api: # if by API then find the API wrapper relative to this workflow, import it, set up a callback, and run eplus_dir = Path(__file__).parent.parent.absolute() sys.path.insert(0, str(eplus_dir)) from pyenergyplus.api import EnergyPlusAPI x = lambda msg: self.callback("(E+API) " + msg.decode( 'utf-8', errors='ignore')) # x = lambda msg: print("(E+ API) : " + str(msg)) api = EnergyPlusAPI() state = api.state_manager.new_state() api.runtime.callback_message(state, x) api.runtime.set_console_output_status(state, False) # cur_dir = os.getcwd() # os.chdir(output_directory) eplus_return = api.runtime.run_energyplus(state, command_line_args) # os.chdir(cur_dir) if eplus_return != 0: self.callback("E+ FAILED") return EPLaunchWorkflowResponse1( success=False, message="EnergyPlus failed for file: %s!" % full_file_path, column_data={}) else: # if by CLI then just execute the full command line try: for message in self.execute_for_callback( command_line_args, output_directory): self.callback(message) except subprocess.CalledProcessError: self.callback("E+ FAILED") return EPLaunchWorkflowResponse1( success=False, message="EnergyPlus failed for file: %s!" % full_file_path, column_data={}) # if isIP: # set up the ESO and MTR output files for either unit conversion or just ReadVarsESO # *.eso back to eplusout.eso eso_path = os.path.join(output_directory, file_name_no_ext + '.eso') eplusouteso_path = os.path.join(output_directory, 'eplusout.eso') if os.path.exists(eso_path): shutil.copy(eso_path, eplusouteso_path) # *.mtr back to eplusout.mtr mtr_path = os.path.join(output_directory, file_name_no_ext + '.mtr') eplusoutmtr_path = os.path.join(output_directory, 'eplusout.mtr') if os.path.exists(mtr_path): shutil.copy(mtr_path, eplusoutmtr_path) if isIP: # run the ConvertESOMTR program to create IP versions of the timestep based output files if platform.system() == 'Windows': converter = os.path.join(energyplus_root_folder, 'PostProcess', 'convertESOMTRpgm', 'convertESOMTR.exe') else: converter = os.path.join(energyplus_root_folder, 'PostProcess', 'convertESOMTRpgm', 'convertESOMTR') if os.path.exists(converter): txt_orig_path = os.path.join(energyplus_root_folder, 'PostProcess', 'convertESOMTRpgm', 'convert.txt') txt_run_path = os.path.join(output_directory, 'convert.txt') shutil.copy(txt_orig_path, txt_run_path) command_line_args = [converter] try: for message in self.execute_for_callback( command_line_args, output_directory): self.callback(message) except subprocess.CalledProcessError: self.callback("ConvertESOMTR FAILED") return EPLaunchWorkflowResponse1( success=False, message="ConvertESOMTR failed for file: %s!" % full_file_path, column_data={}) # copy converted IP version of ESO file to users *.eso file ipeso_path = os.path.join(output_directory, 'ip.eso') if os.path.exists(ipeso_path): shutil.copy(ipeso_path, eso_path) os.replace(ipeso_path, eplusouteso_path) # copy converted IP version of MTR file to users *.mtr file ipmtr_path = os.path.join(output_directory, 'ip.mtr') if os.path.exists(ipmtr_path): shutil.copy(ipmtr_path, mtr_path) os.replace(ipmtr_path, eplusoutmtr_path) os.remove(txt_run_path) # run ReadVarsESO to convert the timestep based output files to CSV files if platform.system() == 'Windows': readvarseso_binary = os.path.join(energyplus_root_folder, 'PostProcess', 'ReadVarsESO.exe') else: readvarseso_binary = os.path.join(energyplus_root_folder, 'PostProcess', 'ReadVarsESO') if os.path.exists(readvarseso_binary): command_line_args = [readvarseso_binary] rvi_path = os.path.join(run_directory, file_name_no_ext + '.rvi') temp_rvi_path = os.path.join(output_directory, 'temp.rvi') eplusout_rvi_path = os.path.join(output_directory, 'eplusout.rvi') if os.path.exists(rvi_path): shutil.copy(rvi_path, eplusout_rvi_path) command_line_args.append('eplusout.rvi') else: with open(temp_rvi_path, "w") as f: f.write('eplusout.eso \n') f.write('eplusout.csv \n') command_line_args.append('temp.rvi') command_line_args.append('unlimited') # no number of column limit try: for message in self.execute_for_callback( command_line_args, output_directory): self.callback(message) except subprocess.CalledProcessError: self.callback("ReadVarsESO FAILED on ESO file") return EPLaunchWorkflowResponse1( success=False, message="ReadVarsESO failed for ESO file: %s!" % full_file_path, column_data={}) vari_csv_path = os.path.join(run_directory, file_name_no_ext + '.csv') # TODO: What is this? eplusout_csv_path = os.path.join(output_directory, 'eplusout.csv') if os.path.exists(eplusout_csv_path): os.replace(eplusout_csv_path, vari_csv_path) command_line_args = [readvarseso_binary] mvi_path = os.path.join(run_directory, file_name_no_ext + '.mvi') temp_mvi_path = os.path.join(output_directory, 'temp.mvi') eplusout_mvi_path = os.path.join(output_directory, 'eplusout.mvi') if os.path.exists(mvi_path): shutil.copy(mvi_path, eplusout_mvi_path) command_line_args.append('eplusout.mvi') else: with open(temp_mvi_path, "w+") as f: f.write('eplusout.mtr \n') f.write('eplusmtr.csv \n') command_line_args.append('temp.mvi') command_line_args.append('unlimited') # no number of column limit try: for message in self.execute_for_callback( command_line_args, output_directory): self.callback(message) except subprocess.CalledProcessError: self.callback("ReadVarsESO FAILED on MTR file") return EPLaunchWorkflowResponse1( success=False, message="ReadVarsESO failed for MTR file: %s!" % full_file_path, column_data={}) mtr_csv_path = os.path.join(output_directory, file_name_no_ext + 'Meter.csv') eplusmtr_csv_path = os.path.join(output_directory, 'eplusmtr.csv') if os.path.exists(eplusmtr_csv_path): os.replace(eplusmtr_csv_path, mtr_csv_path) readvars_audit_path = os.path.join(output_directory, 'readvars.audit') rv_audit_path = os.path.join(output_directory, file_name_no_ext + '.rvaudit') if os.path.exists(readvars_audit_path): os.replace(readvars_audit_path, rv_audit_path) # clean up things inside this IF block delete_if_exists(temp_rvi_path) delete_if_exists(temp_mvi_path) delete_if_exists(eplusout_rvi_path) delete_if_exists(eplusout_mvi_path) # clean up more things delete_if_exists(eplusouteso_path) delete_if_exists(eplusoutmtr_path) audit_out_path = os.path.join(output_directory, 'audit.out') delete_if_exists(audit_out_path) expanded_idf_path = os.path.join(output_directory, 'expanded.idf') delete_if_exists(expanded_idf_path) out_idf_path = os.path.join(output_directory, 'out.idf') delete_if_exists(out_idf_path) # run HVAC-Diagram if platform.system() == 'Windows': hvac_diagram_binary = os.path.join(energyplus_root_folder, 'PostProcess', 'HVAC-Diagram.exe') else: hvac_diagram_binary = os.path.join(energyplus_root_folder, 'PostProcess', 'HVAC-Diagram') if os.path.exists(hvac_diagram_binary): bnd_path = os.path.join(output_directory, file_name_no_ext + '.bnd') eplusout_bnd_path = os.path.join(output_directory, 'eplusout.bnd') if os.path.exists(bnd_path): shutil.copy(bnd_path, eplusout_bnd_path) command_line_args = [hvac_diagram_binary] try: for message in self.execute_for_callback( command_line_args, output_directory): self.callback(message) except subprocess.CalledProcessError: self.callback("HVAC-Diagram FAILED on BND file") return EPLaunchWorkflowResponse1( success=False, message="HVAC-Diagram failed for BND file: %s!" % full_file_path, column_data={}) svg_path = os.path.join(output_directory, file_name_no_ext + '.svg') eplusout_svg_path = os.path.join(output_directory, 'eplusout.svg') if os.path.exists(eplusout_svg_path): os.replace(eplusout_svg_path, svg_path) if os.path.exists(eplusout_bnd_path): os.remove(eplusout_bnd_path) # Now the last thing to do is to collect all the relevant output files for this simulation and put them back # in the original run directory. This is because EP Launch will expect to find them right there. file_names_to_copy = [ f for f in os.listdir(output_directory) if f.startswith(file_name_no_ext) ] for f in file_names_to_copy: shutil.copy(os.path.join(output_directory, f), os.path.join(run_directory, f)) # check on .end file and finish up err_file_name = "{0}.err".format(file_name_no_ext) err_file_path = os.path.join(output_directory, err_file_name) success, errors, warnings, runtime = EPlusRunManager.get_end_summary_from_err( err_file_path) column_data = { ColumnNames.Errors: errors, ColumnNames.Warnings: warnings, ColumnNames.Runtime: runtime, ColumnNames.Version: current_version } # now leave return EPLaunchWorkflowResponse1( success=True, message="Ran EnergyPlus OK for file: %s!" % file_name, column_data=column_data)