Skip to content

Commit

Permalink
fix(simulate): Add a component to create an OSM from a Measure
Browse files Browse the repository at this point in the history
  • Loading branch information
chriswmackey authored and Chris Mackey committed Oct 30, 2023
1 parent 19e7dd7 commit 4963f7a
Show file tree
Hide file tree
Showing 4 changed files with 203 additions and 0 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
64 changes: 64 additions & 0 deletions honeybee_grasshopper_energy/json/HB_Create_OSM_Measure.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
"version": "1.7.0",
"nickname": "OSMMeasure",
"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) and\nit includes measures to create the OSM from the measure",
"type": null,
"default": null
},
{
"access": "None",
"name": "osm",
"description": "The file path to the OpenStudio Model (OSM) that has been generated\non this computer.",
"type": null,
"default": null
},
{
"access": "None",
"name": "idf",
"description": "The file path of the EnergyPlus Input Data File (IDF) that has been\ngenerated on this computer.",
"type": null,
"default": null
}
]
],
"inputs": [
{
"access": "item",
"name": "_measure",
"description": "A Measure from the \"HB Load Measure\" component that is intended to\ngenerate an OSM from input arguments. Measures can be downloaded\nfrom the NREL Building Components Library (BCL) at (https://bcl.nrel.gov/).",
"type": "System.Object",
"default": null
},
{
"access": "list",
"name": "add_str_",
"description": "Optional additional text strings here to be written into the IDF.\nThe input here should be complete EnergyPlus objects as a single\nstring following the IDF format. This can be used to add addition\nEnergyPlus outputs in the resulting IDF among other features.",
"type": "System.Object",
"default": null
},
{
"access": "item",
"name": "_folder_",
"description": "An optional folder on this computer, into which the IDF and OSM\nfiles will be written. If none, a sub-folder within the default\nsimulation folder will be used.",
"type": "string",
"default": null
},
{
"access": "item",
"name": "_run",
"description": "Script variable Python",
"type": "bool",
"default": null
}
],
"subcategory": "5 :: Simulate",
"code": "\nimport sys\nimport re\nimport os\nimport json\n\ntry:\n from ladybug.futil import preparedir, nukedir\nexcept ImportError as e:\n raise ImportError('\\nFailed to import ladybug:\\n\\t{}'.format(e))\n\ntry:\n from honeybee.config import folders\nexcept ImportError as e:\n raise ImportError('\\nFailed to import honeybee:\\n\\t{}'.format(e))\n\ntry:\n from honeybee_energy.measure import Measure\n from honeybee_energy.run import run_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\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 _run:\n # check the presence of openstudio and check that the version is compatible\n check_openstudio_version()\n\n # process the simulation folder name and the directory\n _folder_ = folders.default_simulation_folder if _folder_ is None else _folder_\n clean_name = re.sub(r'[^.A-Za-z0-9_-]', '_', _measure.display_name)\n directory = os.path.join(_folder_, clean_name, 'openstudio')\n\n # delete any existing files in the directory and prepare it for simulation\n nukedir(directory, True)\n preparedir(directory)\n\n # create a dictionary representation of the .osw with steps to run\n # the model measure and the simulation parameter measure\n osw_dict = {'steps': []}\n # assign the measure_paths to the osw_dict\n if 'measure_paths' not in osw_dict:\n osw_dict['measure_paths'] = []\n if energy_folders.honeybee_openstudio_gem_path: # include honeybee-openstudio measure path\n measure_dir = os.path.join(energy_folders.honeybee_openstudio_gem_path, 'measures')\n osw_dict['measure_paths'].append(measure_dir)\n\n # add the measure to the OSW\n measure_paths = set() # set of all unique measure paths\n _measure.validate() # ensure that all required arguments have values\n measure_paths.add(os.path.dirname(_measure.folder))\n osw_dict['steps'].append(_measure.to_osw_dict()) # add measure to workflow\n\n # load the inject IDF measure if strings_to_inject have bee specified\n str_inject = None if add_str_ == [] or add_str_[0] is None \\\n else '\\n'.join(add_str_)\n if str_inject is not None and str_inject != '':\n assert energy_folders.inject_idf_measure_path is not None, \\\n 'Additional IDF strings input but the inject_idf measure is not installed.'\n idf_measure = Measure(energy_folders.inject_idf_measure_path)\n inject_idf = os.path.join(directory, 'inject.idf')\n with open(inject_idf, \"w\") as idf_file:\n idf_file.write(str_inject)\n units_arg = idf_measure.arguments[0]\n units_arg.value = inject_idf\n measure_paths.add(os.path.dirname(idf_measure.folder))\n osw_dict['steps'].append(idf_measure.to_osw_dict()) # add measure to workflow\n\n # write the dictionary to a workflow.osw\n for m_path in measure_paths:\n osw_dict['measure_paths'].append(m_path)\n osw_json = os.path.join(directory, 'workflow.osw')\n if (sys.version_info < (3, 0)): # we need to manually encode it as UTF-8\n with open(osw_json, 'w') as fp:\n workflow_str = json.dumps(osw_dict, indent=4, ensure_ascii=False)\n fp.write(workflow_str.encode('utf-8'))\n else:\n with open(osw_json, 'wb', encoding='utf-8') as fp:\n workflow_str = json.dump(osw_dict, fp, indent=4, ensure_ascii=False)\n osw = os.path.abspath(osw_json)\n osm, idf = run_osw(osw, silent=False)\n",
"category": "HB-Energy",
"name": "HB Create OSM Measure",
"description": "Run an OpenStudio Meausre that is intended to create an entire OSM file\n(OpenStudio Model). Examples of such measures include the \"Create DOE\nPrototype Building\" measure such as that wich can be downloaded here:\n_\nhttps://github.com/NREL/openstudio-model-articulation-gem/tree/develop/lib/\nmeasures/create_DOE_prototype_building\n-"
}
139 changes: 139 additions & 0 deletions honeybee_grasshopper_energy/src/HB Create OSM Measure.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# Honeybee: A Plugin for Environmental Analysis (GPL)
# This file is part of Honeybee.
#
# Copyright (c) 2023, 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>

"""
Run an OpenStudio Meausre that is intended to create an entire OSM file
(OpenStudio Model). Examples of such measures include the "Create DOE
Prototype Building" measure such as that wich can be downloaded here:
_
https://github.com/NREL/openstudio-model-articulation-gem/tree/develop/lib/
measures/create_DOE_prototype_building
-
Args:
_measure: A Measure from the "HB Load Measure" component that is intended to
generate an OSM from input arguments. Measures can be downloaded
from the NREL Building Components Library (BCL) at (https://bcl.nrel.gov/).
add_str_: Optional additional text strings here to be written into the IDF.
The input here should be complete EnergyPlus objects as a single
string following the IDF format. This can be used to add addition
EnergyPlus outputs in the resulting IDF among other features.
_folder_: An optional folder on this computer, into which the IDF and OSM
files will be written. If none, a sub-folder within the default
simulation folder will be used.
run_: Set to "True" to run the measure and generate the OSM.
Returns:
report: Reports, errors, warnings.
osw: File path to the OpenStudio Workflow JSON on this machine. This workflow
is executed using the OpenStudio command line interface (CLI) and
it includes measures to create the OSM from the measure
osm: The file path to the OpenStudio Model (OSM) that has been generated
on this computer.
idf: The file path of the EnergyPlus Input Data File (IDF) that has been
generated on this computer.
"""

ghenv.Component.Name = 'HB Create OSM Measure'
ghenv.Component.NickName = 'OSMMeasure'
ghenv.Component.Message = '1.7.0'
ghenv.Component.Category = 'HB-Energy'
ghenv.Component.SubCategory = '5 :: Simulate'
ghenv.Component.AdditionalHelpFromDocStrings = '0'

import sys
import re
import os
import json

try:
from ladybug.futil import preparedir, nukedir
except ImportError as e:
raise ImportError('\nFailed to import ladybug:\n\t{}'.format(e))

try:
from honeybee.config import folders
except ImportError as e:
raise ImportError('\nFailed to import honeybee:\n\t{}'.format(e))

try:
from honeybee_energy.measure import Measure
from honeybee_energy.run import run_osw
from honeybee_energy.config import folders as energy_folders
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
except ImportError as e:
raise ImportError('\nFailed to import ladybug_rhino:\n\t{}'.format(e))


if all_required_inputs(ghenv.Component) and _run:
# check the presence of openstudio and check that the version is compatible
check_openstudio_version()

# process the simulation folder name and the directory
_folder_ = folders.default_simulation_folder if _folder_ is None else _folder_
clean_name = re.sub(r'[^.A-Za-z0-9_-]', '_', _measure.display_name)
directory = os.path.join(_folder_, clean_name, 'openstudio')

# delete any existing files in the directory and prepare it for simulation
nukedir(directory, True)
preparedir(directory)

# create a dictionary representation of the .osw with steps to run
# the model measure and the simulation parameter measure
osw_dict = {'steps': []}
# assign the measure_paths to the osw_dict
if 'measure_paths' not in osw_dict:
osw_dict['measure_paths'] = []
if energy_folders.honeybee_openstudio_gem_path: # include honeybee-openstudio measure path
measure_dir = os.path.join(energy_folders.honeybee_openstudio_gem_path, 'measures')
osw_dict['measure_paths'].append(measure_dir)

# add the measure to the OSW
measure_paths = set() # set of all unique measure paths
_measure.validate() # ensure that all required arguments have values
measure_paths.add(os.path.dirname(_measure.folder))
osw_dict['steps'].append(_measure.to_osw_dict()) # add measure to workflow

# load the inject IDF measure if strings_to_inject have bee specified
str_inject = None if add_str_ == [] or add_str_[0] is None \
else '\n'.join(add_str_)
if str_inject is not None and str_inject != '':
assert energy_folders.inject_idf_measure_path is not None, \
'Additional IDF strings input but the inject_idf measure is not installed.'
idf_measure = Measure(energy_folders.inject_idf_measure_path)
inject_idf = os.path.join(directory, 'inject.idf')
with open(inject_idf, "w") as idf_file:
idf_file.write(str_inject)
units_arg = idf_measure.arguments[0]
units_arg.value = inject_idf
measure_paths.add(os.path.dirname(idf_measure.folder))
osw_dict['steps'].append(idf_measure.to_osw_dict()) # add measure to workflow

# write the dictionary to a workflow.osw
for m_path in measure_paths:
osw_dict['measure_paths'].append(m_path)
osw_json = os.path.join(directory, 'workflow.osw')
if (sys.version_info < (3, 0)): # we need to manually encode it as UTF-8
with open(osw_json, 'w') as fp:
workflow_str = json.dumps(osw_dict, indent=4, ensure_ascii=False)
fp.write(workflow_str.encode('utf-8'))
else:
with open(osw_json, 'wb', encoding='utf-8') as fp:
workflow_str = json.dump(osw_dict, fp, indent=4, ensure_ascii=False)
osw = os.path.abspath(osw_json)
osm, idf = run_osw(osw, silent=False)
Binary file not shown.

0 comments on commit 4963f7a

Please sign in to comment.