-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(simulate): Add a component to create an empty OSM for Ironbug
- Loading branch information
1 parent
687e499
commit ebd3423
Showing
4 changed files
with
220 additions
and
0 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
{ | ||
"version": "1.8.0", | ||
"nickname": "EmptyOSM", | ||
"outputs": [ | ||
[ | ||
{ | ||
"access": "None", | ||
"name": "osw", | ||
"description": "File path to the OpenStudio Workflow JSON on this machine. This workflow\nis executed using the OpenStudio command line interface (CLI), which\nwill create the empty OSM following the input simulation parameter\nspecifications.", | ||
"type": null, | ||
"default": null | ||
}, | ||
{ | ||
"access": "None", | ||
"name": "osm", | ||
"description": "The file path to the empty OpenStudio Model (OSM) that has been generated\non this computer.", | ||
"type": null, | ||
"default": null | ||
}, | ||
{ | ||
"access": "None", | ||
"name": "idf", | ||
"description": "The file path of the empty EnergyPlus Input Data File (IDF) that has been\ngenerated on this computer.", | ||
"type": null, | ||
"default": null | ||
} | ||
] | ||
], | ||
"inputs": [ | ||
{ | ||
"access": "item", | ||
"name": "_epw_file", | ||
"description": "Path to an .epw file on this computer as a text string.", | ||
"type": "string", | ||
"default": null | ||
}, | ||
{ | ||
"access": "item", | ||
"name": "_sim_par_", | ||
"description": "A honeybee Energy SimulationParameter object that describes all\nof the setting for the simulation. If None, some default simulation\nparameters will automatically be used.", | ||
"type": "System.Object", | ||
"default": null | ||
}, | ||
{ | ||
"access": "item", | ||
"name": "_folder_", | ||
"description": "An optional folder on this computer, into which the IDF and result\nfiles will be written.", | ||
"type": "string", | ||
"default": null | ||
}, | ||
{ | ||
"access": "item", | ||
"name": "_write", | ||
"description": "Set to \"True\" to create the empty OSM file.", | ||
"type": "bool", | ||
"default": null | ||
} | ||
], | ||
"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_empty_osm_osw, run_osw\n from honeybee_energy.result.osw import OSW\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\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\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 directory = os.path.join(_folder_, 'openstudio')\n\n # delete any existing files in the directory and prepare it for simulation\n nukedir(directory, True)\n preparedir(directory)\n\n # write the simulation parameter JSON\n sim_par_dict = _sim_par_.to_dict()\n sim_par_json = os.path.join(directory, 'simulation_parameter.json')\n if (sys.version_info < (3, 0)): # we need to manually encode it as UTF-8\n with open(sim_par_json, 'wb') as fp:\n sim_par_str = json.dumps(sim_par_dict, ensure_ascii=False)\n fp.write(sim_par_str.encode('utf-8'))\n else:\n with open(sim_par_json, 'w', encoding='utf-8') as fp:\n sim_par_str = json.dump(sim_par_dict, fp, ensure_ascii=False)\n\n # collect the two jsons for output and write out the osw file\n osw = to_empty_osm_osw(directory, sim_par_json, epw_file=_epw_file)\n\n # run the measure to translate the JSON\n osm, idf = run_osw(osw, silent=True)\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", | ||
"category": "HB-Energy", | ||
"name": "HB Empty OSM", | ||
"description": "Create an empty OpenStudio Model (OSM) file with no building geometry.\n_\nThis is useful as a starting point for OSMs to which detailed Ironbug systems\nwill be added. Such models with only Ironbug HVAC components can simulate\nin EnergyPlus if they use the LoadProfile:Plant object to represent the\nbuilding loads.\n_\nThey are useful for evaluating the performance of such heating/cooling plants\nand, by setting the simulation parameters and EPW file with this component, any\nsizing criteria for the plant components can be set.\n-" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
# Honeybee: A Plugin for Environmental Analysis (GPL) | ||
# This file is part of Honeybee. | ||
# | ||
# Copyright (c) 2024, Ladybug Tools. | ||
# You should have received a copy of the GNU Affero General Public License | ||
# along with Honeybee; If not, see <http://www.gnu.org/licenses/>. | ||
# | ||
# @license AGPL-3.0-or-later <https://spdx.org/licenses/AGPL-3.0-or-later> | ||
|
||
""" | ||
Create an empty OpenStudio Model (OSM) file with no building geometry. | ||
_ | ||
This is useful as a starting point for OSMs to which detailed Ironbug systems | ||
will be added. Such models with only Ironbug HVAC components can simulate | ||
in EnergyPlus if they use the LoadProfile:Plant object to represent the | ||
building loads. | ||
_ | ||
They are useful for evaluating the performance of such heating/cooling plants | ||
and, by setting the simulation parameters and EPW file with this component, any | ||
sizing criteria for the plant components can be set. | ||
- | ||
Args: | ||
_epw_file: Path to an .epw file on this computer as a text string. | ||
_sim_par_: A honeybee Energy SimulationParameter object that describes all | ||
of the setting for the simulation. If None, some default simulation | ||
parameters will automatically be used. | ||
_folder_: An optional folder on this computer, into which the IDF and result | ||
files will be written. | ||
_write: Set to "True" to create the empty OSM file. | ||
Returns: | ||
report: Reports, errors, warnings, etc. | ||
osw: File path to the OpenStudio Workflow JSON on this machine. This workflow | ||
is executed using the OpenStudio command line interface (CLI), which | ||
will create the empty OSM following the input simulation parameter | ||
specifications. | ||
osm: The file path to the empty OpenStudio Model (OSM) that has been generated | ||
on this computer. | ||
idf: The file path of the empty EnergyPlus Input Data File (IDF) that has been | ||
generated on this computer. | ||
""" | ||
|
||
ghenv.Component.Name = 'HB Empty OSM' | ||
ghenv.Component.NickName = 'EmptyOSM' | ||
ghenv.Component.Message = '1.8.0' | ||
ghenv.Component.Category = 'HB-Energy' | ||
ghenv.Component.SubCategory = '5 :: Simulate' | ||
ghenv.Component.AdditionalHelpFromDocStrings = '0' | ||
|
||
import sys | ||
import os | ||
import re | ||
import json | ||
|
||
try: | ||
from ladybug.futil import preparedir, nukedir | ||
from ladybug.epw import EPW | ||
except ImportError as e: | ||
raise ImportError('\nFailed to import ladybug:\n\t{}'.format(e)) | ||
|
||
try: | ||
import honeybee.config as hb_config | ||
except ImportError as e: | ||
raise ImportError('\nFailed to import honeybee:\n\t{}'.format(e)) | ||
|
||
try: | ||
from honeybee_energy.simulation.parameter import SimulationParameter | ||
from honeybee_energy.run import to_empty_osm_osw, run_osw | ||
from honeybee_energy.result.osw import OSW | ||
except ImportError as e: | ||
raise ImportError('\nFailed to import honeybee_energy:\n\t{}'.format(e)) | ||
|
||
try: | ||
from lbt_recipes.version import check_openstudio_version | ||
except ImportError as e: | ||
raise ImportError('\nFailed to import lbt_recipes:\n\t{}'.format(e)) | ||
|
||
try: | ||
from ladybug_rhino.grasshopper import all_required_inputs, give_warning | ||
except ImportError as e: | ||
raise ImportError('\nFailed to import ladybug_rhino:\n\t{}'.format(e)) | ||
|
||
|
||
if all_required_inputs(ghenv.Component) and _write: | ||
# check the presence of openstudio | ||
check_openstudio_version() | ||
|
||
# process the simulation parameters | ||
if _sim_par_ is None: | ||
_sim_par_ = SimulationParameter() | ||
_sim_par_.output.add_zone_energy_use() | ||
_sim_par_.output.add_hvac_energy_use() | ||
_sim_par_.output.add_electricity_generation() | ||
else: | ||
_sim_par_ = _sim_par_.duplicate() # ensure input is not edited | ||
|
||
# assign design days from the DDY next to the EPW if there are None | ||
if len(_sim_par_.sizing_parameter.design_days) == 0: | ||
msg = None | ||
folder, epw_file_name = os.path.split(_epw_file) | ||
ddy_file = os.path.join(folder, epw_file_name.replace('.epw', '.ddy')) | ||
if os.path.isfile(ddy_file): | ||
try: | ||
_sim_par_.sizing_parameter.add_from_ddy_996_004(ddy_file) | ||
except AssertionError: | ||
msg = 'No ddy_file_ was input into the _sim_par_ sizing ' \ | ||
'parameters\n and no design days were found in the .ddy file '\ | ||
'next to the _epw_file.' | ||
else: | ||
msg = 'No ddy_file_ was input into the _sim_par_ sizing parameters\n' \ | ||
'and no .ddy file was found next to the _epw_file.' | ||
if msg is not None: | ||
epw_obj = EPW(_epw_file) | ||
des_days = [epw_obj.approximate_design_day('WinterDesignDay'), | ||
epw_obj.approximate_design_day('SummerDesignDay')] | ||
_sim_par_.sizing_parameter.design_days = des_days | ||
msg = msg + '\nDesign days were generated from the input _epw_file but this ' \ | ||
'\nis not as accurate as design days from DDYs distributed with the EPW.' | ||
give_warning(ghenv.Component, msg) | ||
print(msg) | ||
|
||
# process the simulation folder name and the directory | ||
_folder_ = hb_config.folders.default_simulation_folder if _folder_ is None else _folder_ | ||
directory = os.path.join(_folder_, 'openstudio') | ||
|
||
# delete any existing files in the directory and prepare it for simulation | ||
nukedir(directory, True) | ||
preparedir(directory) | ||
|
||
# write the simulation parameter JSON | ||
sim_par_dict = _sim_par_.to_dict() | ||
sim_par_json = os.path.join(directory, 'simulation_parameter.json') | ||
if (sys.version_info < (3, 0)): # we need to manually encode it as UTF-8 | ||
with open(sim_par_json, 'wb') as fp: | ||
sim_par_str = json.dumps(sim_par_dict, ensure_ascii=False) | ||
fp.write(sim_par_str.encode('utf-8')) | ||
else: | ||
with open(sim_par_json, 'w', encoding='utf-8') as fp: | ||
sim_par_str = json.dump(sim_par_dict, fp, ensure_ascii=False) | ||
|
||
# collect the two jsons for output and write out the osw file | ||
osw = to_empty_osm_osw(directory, sim_par_json, epw_file=_epw_file) | ||
|
||
# run the measure to translate the JSON | ||
osm, idf = run_osw(osw, silent=True) | ||
if idf is None: # measures failed to run correctly; parse out.osw | ||
log_osw = OSW(os.path.join(directory, 'out.osw')) | ||
errors = [] | ||
for error, tb in zip(log_osw.errors, log_osw.error_tracebacks): | ||
if 'Cannot create a surface' in error: | ||
error = 'Your Rhino Model units system is: {}. ' \ | ||
'Is this correct?\n{}'.format(units_system(), error) | ||
print(tb) | ||
errors.append(error) | ||
raise Exception('Failed to run OpenStudio CLI:\n{}'.format('\n'.join(errors))) |
Binary file not shown.