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

Fix: Parametric schedules error when profiles not matched #1775

Merged
merged 3 commits into from
Jul 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion lib/openstudio-standards/schedules/parametric.rb
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,10 @@ def self.schedule_ruleset_get_parametric_inputs(schedule_ruleset, space_load_ins

# set scheduleRuleset properties
props = schedule_ruleset.additionalProperties

# don't need to gather more than once
return parametric_inputs if props.getFeatureAsString('param_sch_ver') == '0.0.1'

props.setFeature('param_sch_ver', '0.0.1') # this is needed to see if formulas are in sync with version of standards that processes them also used to flag schedule as parametric
props.setFeature('param_sch_floor', min_max['min'])
props.setFeature('param_sch_ceiling', min_max['max'])
Expand All @@ -525,8 +529,11 @@ def self.schedule_ruleset_get_parametric_inputs(schedule_ruleset, space_load_ins
sch_ruleset_days_used = OpenstudioStandards::Schedules.schedule_ruleset_get_annual_days_used(schedule_ruleset)

# match up schedule rule days with hours of operation days
# sch_day_map is a hash where keys are the rule indices of the schedule
# and values are hashes where keys are the hours of operation rule index, and values are arrays of days that the shcedu
sch_day_map = {}
sch_ruleset_days_used.each do |sch_index, sch_days|
# first create a hash that maps each day index to the hoo index that covers that day
day_map = {}
sch_days.each do |day|
# find the hour of operation rule that contains the day number
Expand Down Expand Up @@ -555,6 +562,8 @@ def self.schedule_ruleset_get_parametric_inputs(schedule_ruleset, space_load_ins
# skip if rules already match
if (sch_ruleset_days_used[sch_index] - day_group).empty?
OpenStudio.logFree(OpenStudio::Debug, 'openstudio.standards.Parametric.Schedules', "in #{__method__}: #{schedule_ruleset.name} rule #{sch_index} already matches hours of operation rule #{hoo_index}; new rule won't be created.")
# iterate new_rule_ct anyway to keep these rules
new_rule_ct += 1 unless sch_index == -1
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Iterating this counter when rules already match an hours_of_operation rule (except when it's the default profile) means those rules won't inadvertently be removed below.

next
end
# create new rules
Expand All @@ -563,7 +572,9 @@ def self.schedule_ruleset_get_parametric_inputs(schedule_ruleset, space_load_ins
end
end
# new rules are created at top of list - cleanup old rules
schedule_ruleset.scheduleRules[new_rule_ct..-1].each(&:remove) unless new_rule_ct == 0
if !(new_rule_ct == 0 || new_rule_ct == schedule_ruleset.scheduleRules.size)
schedule_ruleset.scheduleRules[new_rule_ct..].each(&:remove)
end
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This cleans up old rules that don't match hours_of_operation rules.


# re-collect new schedule rules
schedule_days = OpenstudioStandards::Schedules.schedule_ruleset_get_schedule_day_rule_indices(schedule_ruleset)
Expand Down
20 changes: 17 additions & 3 deletions lib/openstudio-standards/weather/modify.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ def self.model_set_undisturbed_ground_temperature_shallow(model, stat_file: nil)
stat_file = OpenstudioStandards::Weather::StatFile.load(weather_file_path.sub('.epw', '.stat'))
end

if stat_file.monthly_undis_ground_temps_0p5m.empty?
return false
end

# set ground temperature shallow values based on .stat file
ground_temperature_shallow = OpenStudio::Model::SiteGroundTemperatureShallow.new(model)
ground_temperature_shallow.setJanuarySurfaceGroundTemperature(stat_file.monthly_undis_ground_temps_0p5m[0])
Expand Down Expand Up @@ -104,6 +108,10 @@ def self.model_set_undisturbed_ground_temperature_deep(model, stat_file: nil)
stat_file = OpenstudioStandards::Weather::StatFile.load(weather_file_path.sub('.epw', '.stat'))
end

if stat_file.monthly_undis_ground_temps_4p0m.empty?
return false
end

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

avoid trying to set data that doesn't exist

# set ground temperature deep values based on .stat file
ground_temperature_deep = OpenStudio::Model::SiteGroundTemperatureDeep.new(model)
ground_temperature_deep.setJanuaryDeepGroundTemperature(stat_file.monthly_undis_ground_temps_4p0m[0])
Expand Down Expand Up @@ -364,7 +372,7 @@ def self.model_set_building_location(model,
ddy_list: nil)
# check that either weather_file_path or climate_zone provided
if weather_file_path.nil? && climate_zone.nil?
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Weather.modify', 'model_set_building_location must be called with either the weather_file_path or climate_zone argument specified.')
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Weather.modify', "#{__method__} must be called with either the weather_file_path or climate_zone argument specified.")
return false
end

Expand All @@ -389,8 +397,14 @@ def self.model_set_building_location(model,
if File.file?(stat_file_path)
stat_file = OpenstudioStandards::Weather::StatFile.load(stat_file_path)
OpenstudioStandards::Weather.model_set_site_water_mains_temperature(model, stat_file: stat_file)
OpenstudioStandards::Weather.model_set_undisturbed_ground_temperature_shallow(model, stat_file: stat_file)
OpenstudioStandards::Weather.model_set_undisturbed_ground_temperature_deep(model, stat_file: stat_file)
if !OpenstudioStandards::Weather.model_set_undisturbed_ground_temperature_shallow(model, stat_file: stat_file)
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Weather.modify', "Could not find undisturbed shallow ground temps in .stat file at #{stat_file_path}. Unable to set undisturbed ground temperatures.")
end

if !OpenstudioStandards::Weather.model_set_undisturbed_ground_temperature_deep(model, stat_file: stat_file)
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Weather.modify', "Could not find undisturbed deep ground temps in .stat file at #{stat_file_path}. Unable to set undisturbed ground temperatures.")
end

stat_file_climate_zone = stat_file.climate_zone
else
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Weather.modify', "Could not find .stat file at #{stat_file_path}. Unable to set site water mains temperature and undisturbed ground temperatures.")
Expand Down