Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add measure for ShadowCalculation #131

Closed
wants to merge 12 commits into from
4 changes: 4 additions & 0 deletions .github/workflows/test_with_openstudio.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ jobs:
ruby -v
openstudio openstudio_version
openstudio gem_list
- name: set git config options
shell: bash
run: |
git config --global --add safe.directory '*'
- name: install dependencies
shell: bash
run: |
Expand Down
27 changes: 27 additions & 0 deletions lib/measures/shadow_calculation/LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
OpenStudio(R), Copyright (c) 2008-2022, Alliance for Sustainable Energy, LLC. All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted
provided that the following conditions are met:

(1) Redistributions of source code must retain the above copyright notice, this list of conditions
and the following disclaimer.

(2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions
and the following disclaimer in the documentation and/or other materials provided with the distribution.

(3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse
or promote products derived from this software without specific prior written permission from the
respective party.

(4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other
derivative works may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar
designation without specific prior written permission from Alliance for Sustainable Energy, LLC.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER, THE UNITED STATES GOVERNMENT,
OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
80 changes: 80 additions & 0 deletions lib/measures/shadow_calculation/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@


###### (Automatically generated documentation)

# Shadow Calculation

## Description
This measure sets the fields of the ShadowCalculation object, which is used to control some details of EnergyPlus’s solar, shadowing, and daylighting models.

## Modeler Description
The ShadowCalculation class does not have a public constructor because it is a unique ModelObject.

## Measure Type
ModelMeasure

## Taxonomy


## Arguments


### Shading Calculation Method

**Name:** shading_calculation_method,
**Type:** Choice,
**Units:** ,
**Required:** true,
**Model Dependent:** false

### Shading Calculation Update Frequency Method

**Name:** shading_calculation_update_frequency_method,
**Type:** Choice,
**Units:** ,
**Required:** false,
**Model Dependent:** false

### Shading Calculation Update Frequency (days)
Shading Calculation Update Frequency Method = Periodic
**Name:** shading_calculation_update_frequency,
**Type:** Integer,
**Units:** ,
**Required:** false,
**Model Dependent:** false

### Maximum Figures in Shadow Overlap Calculations
Shading Calculation Method = PolygonClipping
**Name:** maximum_figures_in_shadow_overlap_calculations,
**Type:** Integer,
**Units:** ,
**Required:** false,
**Model Dependent:** false

### Polygon Clipping Algorithm
Shading Calculation Method = PolygonClipping
**Name:** polygon_clipping_algorithm,
**Type:** Choice,
**Units:** ,
**Required:** false,
**Model Dependent:** false

### Pixel Counting Resolution
Shading Calculation Method = PixelCounting
**Name:** pixel_counting_resolution,
**Type:** Integer,
**Units:** ,
**Required:** false,
**Model Dependent:** false

### Sky Diffuse Modeling Algorithm

**Name:** sky_diffuse_modeling_algorithm,
**Type:** Choice,
**Units:** ,
**Required:** false,
**Model Dependent:** false




42 changes: 42 additions & 0 deletions lib/measures/shadow_calculation/README.md.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<%#= README.md.erb is used to auto-generate README.md. %>
<%#= To manually maintain README.md throw away README.md.erb and manually edit README.md %>
###### (Automatically generated documentation)

# <%= name %>

## Description
<%= description %>

## Modeler Description
<%= modelerDescription %>

## Measure Type
<%= measureType %>

## Taxonomy
<%= taxonomy %>

## Arguments

<% arguments.each do |argument| %>
### <%= argument[:display_name] %>
<%= argument[:description] %>
**Name:** <%= argument[:name] %>,
**Type:** <%= argument[:type] %>,
**Units:** <%= argument[:units] %>,
**Required:** <%= argument[:required] %>,
**Model Dependent:** <%= argument[:model_dependent] %>
<% end %>

<% if arguments.size == 0 %>
<%= "This measure does not have any user arguments" %>
<% end %>

<% if outputs.size > 0 %>
## Outputs
<% output_names = [] %>
<% outputs.each do |output| %>
<% output_names << output[:display_name] %>
<% end %>
<%= output_names.join(", ") %>
<% end %>
183 changes: 183 additions & 0 deletions lib/measures/shadow_calculation/measure.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
# see the URL below for information on how to write OpenStudio measures
# http://nrel.github.io/OpenStudio-user-documentation/reference/measure_writing_guide/

# start the measure
class ShadowCalculation < OpenStudio::Measure::ModelMeasure
# human readable name
def name
# Measure name should be the title case of the class name.
return 'Shadow Calculation'
end

# human readable description
def description
return "This measure sets the fields of the ShadowCalculation object, which is used to control some details of EnergyPlus’s solar, shadowing, and daylighting models."
end

# human readable description of modeling approach
def modeler_description
return "The ShadowCalculation class does not have a public constructor because it is a unique ModelObject."
end

# define the arguments that the user will input
def arguments(model)
args = OpenStudio::Measure::OSArgumentVector.new

shading_calculation_methods = OpenStudio::StringVector.new
shading_calculation_methods << 'PolygonClipping'
shading_calculation_methods << 'PixelCounting'
# # TODO
# shading_calculation_methods << 'Scheduled'
# shading_calculation_methods << 'Imported'
shading_calculation_method = OpenStudio::Measure::OSArgument.makeChoiceArgument('shading_calculation_method', shading_calculation_methods, true)
shading_calculation_method.setDisplayName('Shading Calculation Method')
shading_calculation_method.setDefaultValue('PolygonClipping')
args << shading_calculation_method

shading_calculation_update_frequency_methods = OpenStudio::StringVector.new
shading_calculation_update_frequency_methods << 'Periodic'
shading_calculation_update_frequency_methods << 'Timestep'
shading_calculation_update_frequency_method = OpenStudio::Measure::OSArgument.makeChoiceArgument('shading_calculation_update_frequency_method', shading_calculation_update_frequency_methods, false)
shading_calculation_update_frequency_method.setDisplayName('Shading Calculation Update Frequency Method')
# shading_calculation_update_frequency_method.setDefaultValue('Periodic')
args << shading_calculation_update_frequency_method

shading_calculation_update_frequency = OpenStudio::Measure::OSArgument::makeIntegerArgument('shading_calculation_update_frequency', false)
shading_calculation_update_frequency.setDisplayName('Shading Calculation Update Frequency (days)')
shading_calculation_update_frequency.setDescription('Shading Calculation Update Frequency Method = Periodic')
shading_calculation_update_frequency.setDefaultValue(20)
args << shading_calculation_update_frequency

maximum_figures_in_shadow_overlap_calculations = OpenStudio::Measure::OSArgument::makeIntegerArgument('maximum_figures_in_shadow_overlap_calculations', false)
maximum_figures_in_shadow_overlap_calculations.setDisplayName('Maximum Figures in Shadow Overlap Calculations')
maximum_figures_in_shadow_overlap_calculations.setDescription('Shading Calculation Method = PolygonClipping')
maximum_figures_in_shadow_overlap_calculations.setDefaultValue(15000)
args << maximum_figures_in_shadow_overlap_calculations

polygon_clipping_algorithms = OpenStudio::StringVector.new
polygon_clipping_algorithms << 'SutherlandHodgman'
polygon_clipping_algorithms << 'ConvexWeilerAtherton'
polygon_clipping_algorithms << 'SlaterBarskyandSutherlandHodgman'
polygon_clipping_algorithm = OpenStudio::Measure::OSArgument::makeChoiceArgument('polygon_clipping_algorithm', polygon_clipping_algorithms, false)
polygon_clipping_algorithm.setDisplayName('Polygon Clipping Algorithm')
polygon_clipping_algorithm.setDescription('Shading Calculation Method = PolygonClipping')
# polygon_clipping_algorithm.setDefaultValue('SutherlandHodgman')
args << polygon_clipping_algorithm

pixel_counting_resolution = OpenStudio::Measure::OSArgument::makeIntegerArgument('pixel_counting_resolution', false)
pixel_counting_resolution.setDisplayName('Pixel Counting Resolution')
pixel_counting_resolution.setDescription('Shading Calculation Method = PixelCounting')
pixel_counting_resolution.setDefaultValue(512)
args << pixel_counting_resolution

# This field applies to the shading calculation update frequency method called “Periodic.” When the method called “Timestep” is used the diffuse sky modeling always uses DetailedSkyDiffuseModeling.
sky_diffuse_modeling_algorithms = OpenStudio::StringVector.new
sky_diffuse_modeling_algorithms << 'SimpleSkyDiffuseModeling'
sky_diffuse_modeling_algorithms << 'DetailedSkyDiffuseModeling'
sky_diffuse_modeling_algorithm = OpenStudio::Measure::OSArgument::makeChoiceArgument('sky_diffuse_modeling_algorithm', sky_diffuse_modeling_algorithms, false)
sky_diffuse_modeling_algorithm.setDisplayName('Sky Diffuse Modeling Algorithm')
# sky_diffuse_modeling_algorithm.setDefaultValue('SimpleSkyDiffuseModeling')
args << sky_diffuse_modeling_algorithm

# # TODO requires Shading Calculation Method = Imported
# output_external_shading_calculation_results = OpenStudio::Measure::OSArgument::makeBoolArgument('output_external_shading_calculation_results', true)
# output_external_shading_calculation_results.setDisplayName('Output External Shading Calculation Results')
# output_external_shading_calculation_results.setDefaultValue(false)
# args << output_external_shading_calculation_results

# # TODO requires Shading Zone Group, a vector of ThermalZones
# disable_self_shading_within_shading_zone_groups = OpenStudio::Measure::OSArgument::makeBoolArgument('disable_self_shading_within_shading_zone_groups', true)
# disable_self_shading_within_shading_zone_groups.setDisplayName('Disable Self-Shading Within Shading Zone Groups')
# disable_self_shading_within_shading_zone_groups.setDefaultValue(false)
# args << disable_self_shading_within_shading_zone_groups

# # TODO requires Shading Zone Group, a vector of ThermalZones
# disable_self_shading_from_shading_zone_groupsto_other_zones = OpenStudio::Measure::OSArgument::makeBoolArgument('disable_self_shading_from_shading_zone_groupsto_other_zones', true)
# disable_self_shading_from_shading_zone_groupsto_other_zones.setDisplayName('Disable Self-Shading From Shading Zone Groups to Other Zones')
# disable_self_shading_from_shading_zone_groupsto_other_zones.setDefaultValue(false)
# args << disable_self_shading_from_shading_zone_groupsto_other_zones

return args
end

# define what happens when the measure is run
def run(model, runner, user_arguments)
super(model, runner, user_arguments)

# use the built-in error checking
if !runner.validateUserArguments(arguments(model), user_arguments)
return false
end

# assign the user inputs to variables
shading_calculation_method = runner.getStringArgumentValue('shading_calculation_method', user_arguments)
if runner.getOptionalStringArgumentValue('shading_calculation_update_frequency_method', user_arguments).is_initialized
shading_calculation_update_frequency_method = runner.getStringArgumentValue('shading_calculation_update_frequency_method', user_arguments)
else
shading_calculation_update_frequency_method = false
end
if runner.getOptionalIntegerArgumentValue('shading_calculation_update_frequency', user_arguments).is_initialized
shading_calculation_update_frequency = runner.getIntegerArgumentValue('shading_calculation_update_frequency', user_arguments)
else
shading_calculation_update_frequency = false
end
if runner.getOptionalIntegerArgumentValue('maximum_figures_in_shadow_overlap_calculations', user_arguments).is_initialized
maximum_figures_in_shadow_overlap_calculations = runner.getIntegerArgumentValue('maximum_figures_in_shadow_overlap_calculations', user_arguments)
else
maximum_figures_in_shadow_overlap_calculations = false
end
if runner.getOptionalStringArgumentValue('polygon_clipping_algorithm', user_arguments).is_initialized
polygon_clipping_algorithm = runner.getStringArgumentValue('polygon_clipping_algorithm', user_arguments)
else
polygon_clipping_algorithm = false
end
if runner.getOptionalIntegerArgumentValue('pixel_counting_resolution', user_arguments).is_initialized
pixel_counting_resolution = runner.getIntegerArgumentValue('pixel_counting_resolution', user_arguments)
else
pixel_counting_resolution = false
end
if runner.getOptionalStringArgumentValue('sky_diffuse_modeling_algorithm', user_arguments).is_initialized
sky_diffuse_modeling_algorithm = runner.getStringArgumentValue('sky_diffuse_modeling_algorithm', user_arguments)
else
sky_diffuse_modeling_algorithm = false
end
# output_external_shading_calculation_results = runner.getBoolArgumentValue('output_external_shading_calculation_results', user_arguments)
# disable_self_shading_within_shading_zone_groups = runner.getBoolArgumentValue('disable_self_shading_within_shading_zone_groups', user_arguments)
# disable_self_shading_from_shading_zone_groups_to_other_zones = runner.getBoolArgumentValue('disable_self_shading_from_shading_zone_groups_to_other_zones', user_arguments)

# get object or create one if it does not yet exist
shadow_calculation = model.getShadowCalculation

# report initial condition
runner.registerInitialCondition("#{shadow_calculation}")

# set object
shadow_calculation.setShadingCalculationMethod(shading_calculation_method)
shadow_calculation.setMaximumFiguresInShadowOverlapCalculations(
maximum_figures_in_shadow_overlap_calculations
) if maximum_figures_in_shadow_overlap_calculations
shadow_calculation.setPolygonClippingAlgorithm(
polygon_clipping_algorithm
) if polygon_clipping_algorithm
shadow_calculation.setPixelCountingResolution(
pixel_counting_resolution
) if pixel_counting_resolution
shadow_calculation.setShadingCalculationUpdateFrequencyMethod(
shading_calculation_update_frequency_method
) if shading_calculation_update_frequency_method
shadow_calculation.setShadingCalculationUpdateFrequency(
shading_calculation_update_frequency
) if shading_calculation_update_frequency
shadow_calculation.setSkyDiffuseModelingAlgorithm(
sky_diffuse_modeling_algorithm
) if sky_diffuse_modeling_algorithm

# report final condition
runner.registerFinalCondition("#{shadow_calculation}")

return true
end
end

# register the measure to be used by the application
ShadowCalculation.new.registerWithApplication
Loading