From 9d96dcd8aa0726c09cb62369c489820346721a70 Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 18 Mar 2024 16:45:06 -0500 Subject: [PATCH] fix(simulate): Add a better error message when the input is not a Model --- .../icon/HB Model to OSM.png | Bin 1515 -> 1515 bytes .../json/HB_Model_to_OSM.json | 4 ++-- .../src/HB Model to OSM.py | 5 ++++- .../user_objects/HB Model to OSM.ghuser | Bin 9832 -> 9902 bytes 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/honeybee_grasshopper_energy/icon/HB Model to OSM.png b/honeybee_grasshopper_energy/icon/HB Model to OSM.png index 138888986310d39dcf87e6ad662bf08fea7bda80..4f679bf20b9b87ba977ee30bcb355c1716666349 100644 GIT binary patch delta 34 pcmaFO{hE8jELO%9lV`Kqh)m=;B(cGQLxcecJYD@<);T3K0RYmb3e^Ar delta 34 pcmaFO{hE8jELO%flV`Kqh)iNVB)KK=?G6SY@O1TaS?83{1OVzU42l2% diff --git a/honeybee_grasshopper_energy/json/HB_Model_to_OSM.json b/honeybee_grasshopper_energy/json/HB_Model_to_OSM.json index 1f9ef8b..52d8440 100644 --- a/honeybee_grasshopper_energy/json/HB_Model_to_OSM.json +++ b/honeybee_grasshopper_energy/json/HB_Model_to_OSM.json @@ -1,5 +1,5 @@ { - "version": "1.7.3", + "version": "1.7.4", "nickname": "ModelToOSM", "outputs": [ [ @@ -120,7 +120,7 @@ } ], "subcategory": "5 :: Simulate", - "code": "\nimport sys\nimport os\nimport re\nimport json\n\ntry:\n from ladybug.futil import preparedir, nukedir\n from ladybug.epw import EPW\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug:\\n\\t{}'.format(e))\n\ntry:\n import honeybee.config as hb_config\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee:\\n\\t{}'.format(e))\n\ntry:\n from honeybee_energy.simulation.parameter import SimulationParameter\n from honeybee_energy.run import to_openstudio_osw, run_osw, run_idf, \\\n output_energyplus_files\n from honeybee_energy.result.err import Err\n from honeybee_energy.result.osw import OSW\n from honeybee_energy.config import folders as energy_folders\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee_energy:\\n\\t{}'.format(e))\n\ntry:\n from lbt_recipes.version import check_openstudio_version\nexcept ImportError as e:\n raise ImportError('\\nFailed to import lbt_recipes:\\n\\t{}'.format(e))\n\ntry:\n from ladybug_{{cad}}.{{plugin}} import all_required_inputs, give_warning\n from ladybug_{{cad}}.config import units_system\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_{{cad}}:\\n\\t{}'.format(e))\n\n\nif all_required_inputs(ghenv.Component) and _write:\n # check the presence of openstudio and check that the version is compatible\n check_openstudio_version()\n\n # process the simulation parameters\n if _sim_par_ is None:\n _sim_par_ = SimulationParameter()\n _sim_par_.output.add_zone_energy_use()\n _sim_par_.output.add_hvac_energy_use()\n _sim_par_.output.add_electricity_generation()\n else:\n _sim_par_ = _sim_par_.duplicate() # ensure input is not edited\n\n # assign design days from the DDY next to the EPW if there are None\n if len(_sim_par_.sizing_parameter.design_days) == 0:\n msg = None\n folder, epw_file_name = os.path.split(_epw_file)\n ddy_file = os.path.join(folder, epw_file_name.replace('.epw', '.ddy'))\n if os.path.isfile(ddy_file):\n try:\n _sim_par_.sizing_parameter.add_from_ddy_996_004(ddy_file)\n except AssertionError:\n msg = 'No ddy_file_ was input into the _sim_par_ sizing ' \\\n 'parameters\\n and no design days were found in the .ddy file '\\\n 'next to the _epw_file.'\n else:\n msg = 'No ddy_file_ was input into the _sim_par_ sizing parameters\\n' \\\n 'and no .ddy file was found next to the _epw_file.'\n if msg is not None:\n epw_obj = EPW(_epw_file)\n des_days = [epw_obj.approximate_design_day('WinterDesignDay'),\n epw_obj.approximate_design_day('SummerDesignDay')]\n _sim_par_.sizing_parameter.design_days = des_days\n msg = msg + '\\nDesign days were generated from the input _epw_file but this ' \\\n '\\nis not as accurate as design days from DDYs distributed with the EPW.'\n give_warning(ghenv.Component, msg)\n print(msg)\n\n # process the simulation folder name and the directory\n _folder_ = hb_config.folders.default_simulation_folder if _folder_ is None else _folder_\n clean_name = re.sub(r'[^.A-Za-z0-9_-]', '_', _model.display_name)\n directory = os.path.join(_folder_, clean_name, 'openstudio')\n\n # duplicate model to avoid mutating it as we edit it for energy simulation\n _model = _model.duplicate()\n # scale the model if the units are not meters\n if _model.units != 'Meters':\n _model.convert_to_units('Meters')\n # remove degenerate geometry within native E+ tolerance of 0.01 meters\n try:\n _model.remove_degenerate_geometry(0.01)\n except ValueError:\n error = 'Failed to remove degenerate Rooms.\\nYour Model units system is: {}. ' \\\n 'Is this correct?'.format(units_system())\n raise ValueError(error)\n # remove the HVAC from any Rooms lacking setpoints\n rem_msgs = _model.properties.energy.remove_hvac_from_no_setpoints()\n if rem_msgs is not None and len(rem_msgs) != 0:\n msg = '\\n'.join(rem_msgs)\n give_warning(ghenv.Component, msg)\n print(msg)\n\n # auto-assign stories if there are none since most OpenStudio measures need these\n if len(_model.stories) == 0 and len(_model.rooms) != 0:\n _model.assign_stories_by_floor_height()\n\n # delete any existing files in the directory and prepare it for simulation\n nukedir(directory, True)\n preparedir(directory)\n sch_directory = os.path.join(directory, 'schedules')\n preparedir(sch_directory)\n\n # write the model parameter JSONs\n model_dict = _model.to_dict(triangulate_sub_faces=True)\n _model.properties.energy.add_autocal_properties_to_dict(model_dict)\n model_json = os.path.join(directory, '{}.hbjson'.format(clean_name))\n if (sys.version_info < (3, 0)): # we need to manually encode it as UTF-8\n with open(model_json, 'wb') as fp:\n model_str = json.dumps(model_dict, ensure_ascii=False)\n fp.write(model_str.encode('utf-8'))\n else:\n with open(model_json, 'w', encoding='utf-8') as fp:\n model_str = json.dump(model_dict, fp, ensure_ascii=False)\n\n # write the simulation parameter JSONs\n sim_par_dict = _sim_par_.to_dict()\n sim_par_json = os.path.join(directory, 'simulation_parameter.json')\n with open(sim_par_json, 'w') as fp:\n json.dump(sim_par_dict, fp)\n\n # process any measures input to the component\n measures = None if len(measures_) == 0 or measures_[0] is None else measures_\n no_report_meas = True if measures is None else \\\n all(meas.type != 'ReportingMeasure' for meas in measures)\n str_inject = None if no_report_meas or add_str_ == [] or add_str_[0] is None \\\n else '\\n'.join(add_str_)\n\n # collect the two jsons for output and write out the osw file\n jsons = [model_json, sim_par_json]\n osw = to_openstudio_osw(\n directory, model_json, sim_par_json, additional_measures=measures,\n epw_file=_epw_file, schedule_directory=sch_directory,\n strings_to_inject=str_inject)\n\n # run the measure to translate the model JSON to an openstudio measure\n silent = True if run_ == 3 else False\n if run_ > 0 and not no_report_meas: # everything must run with OS CLI\n if run_ == 1: # simulate everything at once\n osm, idf = run_osw(osw, measures_only=False, silent=silent)\n sql, zsz, rdd, html, err = output_energyplus_files(os.path.dirname(idf))\n else: # remove reporting measure and give a warning\n m_to_remove = [m.identifier for m in measures if m.type == 'ReportingMeasure']\n with open(osw, 'r') as op:\n osw_data = json.load(op)\n s_to_remove = []\n for i, step in enumerate(osw_data['steps']):\n if step['measure_dir_name'] in m_to_remove:\n s_to_remove.append(i)\n for i in reversed(s_to_remove):\n osw_data['steps'].pop(i)\n with open(osw, 'wb') as fp:\n workflow_str = json.dumps(osw_data, indent=4, ensure_ascii=False)\n fp.write(workflow_str.encode('utf-8'))\n msg = 'The following were reporting measures and were not\\n' \\\n 'included in the OSW to avoid running the simulation:\\n{}'.format(\n '\\n'.join(m_to_remove))\n give_warning(ghenv.Component, msg)\n print(msg)\n osm, idf = run_osw(osw, silent=silent)\n elif run_ > 0: # no reporting measure; simulate separately from measure application\n osm, idf = run_osw(osw, silent=silent)\n # process the additional strings\n if len(add_str_) != 0 and add_str_[0] is not None and idf is not None:\n add_str = '\\n'.join(add_str_)\n with open(idf, \"a\") as idf_file:\n idf_file.write(add_str)\n if idf is None: # measures failed to run correctly; parse out.osw\n log_osw = OSW(os.path.join(directory, 'out.osw'))\n errors = []\n for error, tb in zip(log_osw.errors, log_osw.error_tracebacks):\n if 'Cannot create a surface' in error:\n error = 'Your {{Cad}} Model units system is: {}. ' \\\n 'Is this correct?\\n{}'.format(units_system(), error)\n print(tb)\n errors.append(error)\n raise Exception('Failed to run OpenStudio CLI:\\n{}'.format('\\n'.join(errors)))\n elif run_ in (1, 3): # run the resulting idf throught EnergyPlus\n sql, zsz, rdd, html, err = run_idf(idf, _epw_file, silent=silent)\n\n # parse the error log and report any warnings\n if run_ in (1, 3) and err is not None:\n err_obj = Err(err)\n print(err_obj.file_contents)\n for warn in err_obj.severe_errors:\n give_warning(ghenv.Component, warn)\n for error in err_obj.fatal_errors:\n raise Exception(error)\n", + "code": "\nimport sys\nimport os\nimport re\nimport json\n\ntry:\n from ladybug.futil import preparedir, nukedir\n from ladybug.epw import EPW\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug:\\n\\t{}'.format(e))\n\ntry:\n import honeybee.config as hb_config\n from honeybee.model import Model\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee:\\n\\t{}'.format(e))\n\ntry:\n from honeybee_energy.simulation.parameter import SimulationParameter\n from honeybee_energy.run import to_openstudio_osw, run_osw, run_idf, \\\n output_energyplus_files\n from honeybee_energy.result.err import Err\n from honeybee_energy.result.osw import OSW\n from honeybee_energy.config import folders as energy_folders\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee_energy:\\n\\t{}'.format(e))\n\ntry:\n from lbt_recipes.version import check_openstudio_version\nexcept ImportError as e:\n raise ImportError('\\nFailed to import lbt_recipes:\\n\\t{}'.format(e))\n\ntry:\n from ladybug_{{cad}}.{{plugin}} import all_required_inputs, give_warning\n from ladybug_{{cad}}.config import units_system\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug_{{cad}}:\\n\\t{}'.format(e))\n\n\nif all_required_inputs(ghenv.Component) and _write:\n # check the presence of openstudio and check that the version is compatible\n check_openstudio_version()\n assert isinstance(_model, Model), \\\n 'Expected Honeybee Model for _model input. Got {}.'.format(type(_model))\n\n # process the simulation parameters\n if _sim_par_ is None:\n _sim_par_ = SimulationParameter()\n _sim_par_.output.add_zone_energy_use()\n _sim_par_.output.add_hvac_energy_use()\n _sim_par_.output.add_electricity_generation()\n else:\n _sim_par_ = _sim_par_.duplicate() # ensure input is not edited\n\n # assign design days from the DDY next to the EPW if there are None\n if len(_sim_par_.sizing_parameter.design_days) == 0:\n msg = None\n folder, epw_file_name = os.path.split(_epw_file)\n ddy_file = os.path.join(folder, epw_file_name.replace('.epw', '.ddy'))\n if os.path.isfile(ddy_file):\n try:\n _sim_par_.sizing_parameter.add_from_ddy_996_004(ddy_file)\n except AssertionError:\n msg = 'No ddy_file_ was input into the _sim_par_ sizing ' \\\n 'parameters\\n and no design days were found in the .ddy file '\\\n 'next to the _epw_file.'\n else:\n msg = 'No ddy_file_ was input into the _sim_par_ sizing parameters\\n' \\\n 'and no .ddy file was found next to the _epw_file.'\n if msg is not None:\n epw_obj = EPW(_epw_file)\n des_days = [epw_obj.approximate_design_day('WinterDesignDay'),\n epw_obj.approximate_design_day('SummerDesignDay')]\n _sim_par_.sizing_parameter.design_days = des_days\n msg = msg + '\\nDesign days were generated from the input _epw_file but this ' \\\n '\\nis not as accurate as design days from DDYs distributed with the EPW.'\n give_warning(ghenv.Component, msg)\n print(msg)\n\n # process the simulation folder name and the directory\n _folder_ = hb_config.folders.default_simulation_folder if _folder_ is None else _folder_\n clean_name = re.sub(r'[^.A-Za-z0-9_-]', '_', _model.display_name)\n directory = os.path.join(_folder_, clean_name, 'openstudio')\n\n # duplicate model to avoid mutating it as we edit it for energy simulation\n _model = _model.duplicate()\n # scale the model if the units are not meters\n if _model.units != 'Meters':\n _model.convert_to_units('Meters')\n # remove degenerate geometry within native E+ tolerance of 0.01 meters\n try:\n _model.remove_degenerate_geometry(0.01)\n except ValueError:\n error = 'Failed to remove degenerate Rooms.\\nYour Model units system is: {}. ' \\\n 'Is this correct?'.format(units_system())\n raise ValueError(error)\n # remove the HVAC from any Rooms lacking setpoints\n rem_msgs = _model.properties.energy.remove_hvac_from_no_setpoints()\n if rem_msgs is not None and len(rem_msgs) != 0:\n msg = '\\n'.join(rem_msgs)\n give_warning(ghenv.Component, msg)\n print(msg)\n\n # auto-assign stories if there are none since most OpenStudio measures need these\n if len(_model.stories) == 0 and len(_model.rooms) != 0:\n _model.assign_stories_by_floor_height()\n\n # delete any existing files in the directory and prepare it for simulation\n nukedir(directory, True)\n preparedir(directory)\n sch_directory = os.path.join(directory, 'schedules')\n preparedir(sch_directory)\n\n # write the model parameter JSONs\n model_dict = _model.to_dict(triangulate_sub_faces=True)\n _model.properties.energy.add_autocal_properties_to_dict(model_dict)\n model_json = os.path.join(directory, '{}.hbjson'.format(clean_name))\n if (sys.version_info < (3, 0)): # we need to manually encode it as UTF-8\n with open(model_json, 'wb') as fp:\n model_str = json.dumps(model_dict, ensure_ascii=False)\n fp.write(model_str.encode('utf-8'))\n else:\n with open(model_json, 'w', encoding='utf-8') as fp:\n model_str = json.dump(model_dict, fp, ensure_ascii=False)\n\n # write the simulation parameter JSONs\n sim_par_dict = _sim_par_.to_dict()\n sim_par_json = os.path.join(directory, 'simulation_parameter.json')\n with open(sim_par_json, 'w') as fp:\n json.dump(sim_par_dict, fp)\n\n # process any measures input to the component\n measures = None if len(measures_) == 0 or measures_[0] is None else measures_\n no_report_meas = True if measures is None else \\\n all(meas.type != 'ReportingMeasure' for meas in measures)\n str_inject = None if no_report_meas or add_str_ == [] or add_str_[0] is None \\\n else '\\n'.join(add_str_)\n\n # collect the two jsons for output and write out the osw file\n jsons = [model_json, sim_par_json]\n osw = to_openstudio_osw(\n directory, model_json, sim_par_json, additional_measures=measures,\n epw_file=_epw_file, schedule_directory=sch_directory,\n strings_to_inject=str_inject)\n\n # run the measure to translate the model JSON to an openstudio measure\n silent = True if run_ == 3 else False\n if run_ > 0 and not no_report_meas: # everything must run with OS CLI\n if run_ == 1: # simulate everything at once\n osm, idf = run_osw(osw, measures_only=False, silent=silent)\n sql, zsz, rdd, html, err = output_energyplus_files(os.path.dirname(idf))\n else: # remove reporting measure and give a warning\n m_to_remove = [m.identifier for m in measures if m.type == 'ReportingMeasure']\n with open(osw, 'r') as op:\n osw_data = json.load(op)\n s_to_remove = []\n for i, step in enumerate(osw_data['steps']):\n if step['measure_dir_name'] in m_to_remove:\n s_to_remove.append(i)\n for i in reversed(s_to_remove):\n osw_data['steps'].pop(i)\n with open(osw, 'wb') as fp:\n workflow_str = json.dumps(osw_data, indent=4, ensure_ascii=False)\n fp.write(workflow_str.encode('utf-8'))\n msg = 'The following were reporting measures and were not\\n' \\\n 'included in the OSW to avoid running the simulation:\\n{}'.format(\n '\\n'.join(m_to_remove))\n give_warning(ghenv.Component, msg)\n print(msg)\n osm, idf = run_osw(osw, silent=silent)\n elif run_ > 0: # no reporting measure; simulate separately from measure application\n osm, idf = run_osw(osw, silent=silent)\n # process the additional strings\n if len(add_str_) != 0 and add_str_[0] is not None and idf is not None:\n add_str = '\\n'.join(add_str_)\n with open(idf, \"a\") as idf_file:\n idf_file.write(add_str)\n if idf is None: # measures failed to run correctly; parse out.osw\n log_osw = OSW(os.path.join(directory, 'out.osw'))\n errors = []\n for error, tb in zip(log_osw.errors, log_osw.error_tracebacks):\n if 'Cannot create a surface' in error:\n error = 'Your {{Cad}} Model units system is: {}. ' \\\n 'Is this correct?\\n{}'.format(units_system(), error)\n print(tb)\n errors.append(error)\n raise Exception('Failed to run OpenStudio CLI:\\n{}'.format('\\n'.join(errors)))\n elif run_ in (1, 3): # run the resulting idf throught EnergyPlus\n sql, zsz, rdd, html, err = run_idf(idf, _epw_file, silent=silent)\n\n # parse the error log and report any warnings\n if run_ in (1, 3) and err is not None:\n err_obj = Err(err)\n print(err_obj.file_contents)\n for warn in err_obj.severe_errors:\n give_warning(ghenv.Component, warn)\n for error in err_obj.fatal_errors:\n raise Exception(error)\n", "category": "HB-Energy", "name": "HB Model to OSM", "description": "Write a honeybee Model to an OSM file (OpenStudio Model), which can then be translated\nto an IDF file and then run through EnergyPlus.\n-" diff --git a/honeybee_grasshopper_energy/src/HB Model to OSM.py b/honeybee_grasshopper_energy/src/HB Model to OSM.py index 36dfab6..f6bd178 100644 --- a/honeybee_grasshopper_energy/src/HB Model to OSM.py +++ b/honeybee_grasshopper_energy/src/HB Model to OSM.py @@ -74,7 +74,7 @@ ghenv.Component.Name = 'HB Model to OSM' ghenv.Component.NickName = 'ModelToOSM' -ghenv.Component.Message = '1.7.3' +ghenv.Component.Message = '1.7.4' ghenv.Component.Category = 'HB-Energy' ghenv.Component.SubCategory = '5 :: Simulate' ghenv.Component.AdditionalHelpFromDocStrings = '1' @@ -92,6 +92,7 @@ try: import honeybee.config as hb_config + from honeybee.model import Model except ImportError as e: raise ImportError('\nFailed to import honeybee:\n\t{}'.format(e)) @@ -120,6 +121,8 @@ if all_required_inputs(ghenv.Component) and _write: # check the presence of openstudio and check that the version is compatible check_openstudio_version() + assert isinstance(_model, Model), \ + 'Expected Honeybee Model for _model input. Got {}.'.format(type(_model)) # process the simulation parameters if _sim_par_ is None: diff --git a/honeybee_grasshopper_energy/user_objects/HB Model to OSM.ghuser b/honeybee_grasshopper_energy/user_objects/HB Model to OSM.ghuser index 2472e5ef1406a89063e9e0b77ffcd6ffa86c1a2c..20bedf8d589a428f6156d49f3e06611a62c69e52 100644 GIT binary patch literal 9902 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 Oa|4wvY+U}G?)pEt021N=