honeybee-openstudio 2.10.0 → 2.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile +1 -1
- data/honeybee-openstudio.gemspec +2 -2
- data/lib/files/reopt_assumptions.json +146 -0
- data/lib/files/urbanopt_Gemfile +4 -4
- data/lib/measures/from_honeybee_model/measure.rb +23 -0
- data/lib/to_openstudio/model.rb +65 -5
- data/lib/to_openstudio/schedule/fixed_interval.rb +146 -30
- data/lib/to_openstudio/schedule/ruleset.rb +2 -1
- data/lib/to_openstudio/simulation/parameter_model.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f86f836af76719222d4ce8393755cd79a6243e52e700c40f54808f72b6d9f2bf
|
4
|
+
data.tar.gz: 98176f5bb8055c871951f56b21717f9f6b3efc35e2b87ae5dbf98520cb2eb954
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2d2ddb1e445513e442caf0e7ec9846ce9653a25291cead36e00d7b2ca41e3f8b928d5c5a8ffa79880c11d557293c2af22e211b7be525eef32db3ee315ce15209
|
7
|
+
data.tar.gz: 3f69624f318a6d3dc5dc8db9ddafd850dbe487bf9d135996cfa9e1cd91fb286cbb1f49e63fb825f6e19dba79bda98ee396a604e4c8fe2027e2e0249e91a323a9
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
@@ -7,7 +7,7 @@ gemspec
|
|
7
7
|
if File.exist?('../OpenStudio-extension-gem') # local development copy
|
8
8
|
gem 'openstudio-extension', path: '../OpenStudio-extension-gem'
|
9
9
|
else # get it from rubygems.org
|
10
|
-
gem 'openstudio-extension', '0.2
|
10
|
+
gem 'openstudio-extension', '0.3.2'
|
11
11
|
end
|
12
12
|
|
13
13
|
# coveralls gem is used to generate coverage reports through CI
|
data/honeybee-openstudio.gemspec
CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = 'honeybee-openstudio'
|
7
|
-
spec.version = '2.
|
7
|
+
spec.version = '2.11.0'
|
8
8
|
spec.authors = ['Tanushree Charan', 'Dan Macumber', 'Chris Mackey', 'Mostapha Sadeghipour Roudsari']
|
9
9
|
spec.email = ['tanushree.charan@nrel.gov', 'chris@ladybug.tools']
|
10
10
|
|
@@ -33,6 +33,6 @@ Gem::Specification.new do |spec|
|
|
33
33
|
end
|
34
34
|
|
35
35
|
spec.add_dependency 'json_pure'
|
36
|
-
spec.add_dependency 'openstudio-extension', '0.2
|
36
|
+
spec.add_dependency 'openstudio-extension', '0.3.2'
|
37
37
|
spec.add_dependency 'openstudio-standards', '~> 0.2.12'
|
38
38
|
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
{
|
2
|
+
"Scenario": {
|
3
|
+
"Site": {
|
4
|
+
"Financial": {
|
5
|
+
"om_cost_escalation_pct": 0.025,
|
6
|
+
"escalation_pct": 0.023,
|
7
|
+
"offtaker_tax_pct": 0.26,
|
8
|
+
"offtaker_discount_pct": 0.083,
|
9
|
+
"analysis_years": 25,
|
10
|
+
"value_of_lost_load_us_dollars_per_kwh": 100,
|
11
|
+
"microgrid_upgrade_cost_pct": 0.3
|
12
|
+
},
|
13
|
+
"LoadProfile": {
|
14
|
+
"year": 2018,
|
15
|
+
"loads_kw_is_net": true,
|
16
|
+
"critical_loads_kw_is_net": false,
|
17
|
+
"critical_load_pct": 0.5,
|
18
|
+
"outage_is_major_event": true
|
19
|
+
},
|
20
|
+
"ElectricTariff": {
|
21
|
+
"add_blended_rates_to_urdb_rate": false,
|
22
|
+
"net_metering_limit_kw": 0,
|
23
|
+
"interconnection_limit_kw": 100000000.0,
|
24
|
+
"urdb_label": "5e162e2a5457a3d50873e3af"
|
25
|
+
},
|
26
|
+
"Wind": {
|
27
|
+
"min_kw": 0,
|
28
|
+
"max_kw": 0,
|
29
|
+
"installed_cost_us_dollars_per_kw": 3013,
|
30
|
+
"om_cost_us_dollars_per_kw": 40,
|
31
|
+
"macrs_option_years": 5,
|
32
|
+
"macrs_bonus_pct": 1,
|
33
|
+
"macrs_itc_reduction": 0.5,
|
34
|
+
"federal_itc_pct": 0.26,
|
35
|
+
"state_ibi_pct": 0,
|
36
|
+
"state_ibi_max_us_dollars": 10000000000.0,
|
37
|
+
"utility_ibi_pct": 0,
|
38
|
+
"utility_ibi_max_us_dollars": 10000000000.0,
|
39
|
+
"federal_rebate_us_dollars_per_kw": 0,
|
40
|
+
"state_rebate_us_dollars_per_kw": 0,
|
41
|
+
"state_rebate_max_us_dollars": 10000000000.0,
|
42
|
+
"utility_rebate_us_dollars_per_kw": 0,
|
43
|
+
"utility_rebate_max_us_dollars": 10000000000.0,
|
44
|
+
"pbi_us_dollars_per_kwh": 0,
|
45
|
+
"pbi_max_us_dollars": 1000000000.0,
|
46
|
+
"pbi_years": 1,
|
47
|
+
"pbi_system_max_kw": 1000000000.0
|
48
|
+
},
|
49
|
+
"PV": {
|
50
|
+
"pv_name": "Roof - South Face",
|
51
|
+
"location":"roof",
|
52
|
+
"existing_kw": 0,
|
53
|
+
"existing_kw": 0,
|
54
|
+
"min_kw": 0,
|
55
|
+
"max_kw": 1000000000.0,
|
56
|
+
"installed_cost_us_dollars_per_kw": 1600,
|
57
|
+
"om_cost_us_dollars_per_kw": 16,
|
58
|
+
"macrs_option_years": 5,
|
59
|
+
"macrs_bonus_pct": 1,
|
60
|
+
"macrs_itc_reduction": 0.5,
|
61
|
+
"federal_itc_pct": 0.26,
|
62
|
+
"state_ibi_pct": 0,
|
63
|
+
"state_ibi_max_us_dollars": 10000000000.0,
|
64
|
+
"utility_ibi_pct": 0,
|
65
|
+
"utility_ibi_max_us_dollars": 10000000000.0,
|
66
|
+
"federal_rebate_us_dollars_per_kw": 0,
|
67
|
+
"state_rebate_us_dollars_per_kw": 0,
|
68
|
+
"state_rebate_max_us_dollars": 10000000000.0,
|
69
|
+
"utility_rebate_us_dollars_per_kw": 0,
|
70
|
+
"utility_rebate_max_us_dollars": 10000000000.0,
|
71
|
+
"pbi_us_dollars_per_kwh": 0,
|
72
|
+
"pbi_max_us_dollars": 1000000000.0,
|
73
|
+
"pbi_years": 1,
|
74
|
+
"pbi_system_max_kw": 1000000000.0,
|
75
|
+
"degradation_pct": 0.005,
|
76
|
+
"azimuth": 180,
|
77
|
+
"losses": 0.14,
|
78
|
+
"array_type": 1,
|
79
|
+
"module_type": 0,
|
80
|
+
"gcr": 0.4,
|
81
|
+
"dc_ac_ratio": 1.2,
|
82
|
+
"inv_eff": 0.96,
|
83
|
+
"radius": 0,
|
84
|
+
"tilt": 0.537
|
85
|
+
},
|
86
|
+
"Storage": {
|
87
|
+
"min_kw": 0,
|
88
|
+
"max_kw": 1000000,
|
89
|
+
"min_kwh": 0,
|
90
|
+
"max_kwh": 1000000,
|
91
|
+
"internal_efficiency_pct": 0.975,
|
92
|
+
"inverter_efficiency_pct": 0.96,
|
93
|
+
"rectifier_efficiency_pct": 0.96,
|
94
|
+
"soc_min_pct": 0.2,
|
95
|
+
"soc_init_pct": 0.5,
|
96
|
+
"canGridCharge": true,
|
97
|
+
"installed_cost_us_dollars_per_kw": 840,
|
98
|
+
"installed_cost_us_dollars_per_kwh": 420,
|
99
|
+
"replace_cost_us_dollars_per_kw": 410,
|
100
|
+
"replace_cost_us_dollars_per_kwh": 200,
|
101
|
+
"inverter_replacement_year": 10,
|
102
|
+
"battery_replacement_year": 10,
|
103
|
+
"macrs_option_years": 7,
|
104
|
+
"macrs_bonus_pct": 1,
|
105
|
+
"macrs_itc_reduction": 0.5,
|
106
|
+
"total_itc_pct": 0.0,
|
107
|
+
"total_rebate_us_dollars_per_kw": 0
|
108
|
+
},
|
109
|
+
"Generator": {
|
110
|
+
"existing_kw": 0,
|
111
|
+
"min_kw": 0,
|
112
|
+
"max_kw": 1000000000.0,
|
113
|
+
"installed_cost_us_dollars_per_kw": 500,
|
114
|
+
"om_cost_us_dollars_per_kw": 10,
|
115
|
+
"om_cost_us_dollars_per_kwh": 0.0,
|
116
|
+
"diesel_fuel_cost_us_dollars_per_gallon": 3,
|
117
|
+
"fuel_slope_gal_per_kwh": 0.076,
|
118
|
+
"fuel_intercept_gal_per_hr": 0,
|
119
|
+
"fuel_avail_gal": 660,
|
120
|
+
"min_turn_down_pct": 0,
|
121
|
+
"generator_only_runs_during_grid_outage": true,
|
122
|
+
"generator_sells_energy_back_to_grid": false,
|
123
|
+
"macrs_option_years": 0,
|
124
|
+
"macrs_bonus_pct": 1,
|
125
|
+
"macrs_itc_reduction": 0,
|
126
|
+
"federal_itc_pct": 0,
|
127
|
+
"state_ibi_pct": 0,
|
128
|
+
"state_ibi_max_us_dollars": 0,
|
129
|
+
"utility_ibi_pct": 0,
|
130
|
+
"utility_ibi_max_us_dollars": 0,
|
131
|
+
"federal_rebate_us_dollars_per_kw": 0,
|
132
|
+
"state_rebate_us_dollars_per_kw": 0,
|
133
|
+
"state_rebate_max_us_dollars": 0,
|
134
|
+
"utility_rebate_us_dollars_per_kw": 0,
|
135
|
+
"utility_rebate_max_us_dollars": 0,
|
136
|
+
"pbi_us_dollars_per_kwh": 0,
|
137
|
+
"pbi_max_us_dollars": 0,
|
138
|
+
"pbi_years": 0,
|
139
|
+
"pbi_system_max_kw": 0
|
140
|
+
}
|
141
|
+
},
|
142
|
+
"timeout_seconds": 295,
|
143
|
+
"time_steps_per_hour": 1
|
144
|
+
}
|
145
|
+
}
|
146
|
+
|
data/lib/files/urbanopt_Gemfile
CHANGED
@@ -9,7 +9,7 @@ if allow_local && File.exist?('../openstudio-model-articulation-gem')
|
|
9
9
|
elsif allow_local
|
10
10
|
gem 'openstudio-model-articulation', github: 'NREL/openstudio-model-articulation-gem', branch: 'develop'
|
11
11
|
else
|
12
|
-
gem 'openstudio-model-articulation', '0.
|
12
|
+
gem 'openstudio-model-articulation', '0.3.1'
|
13
13
|
end
|
14
14
|
|
15
15
|
if allow_local && File.exist?('../urbanopt-geojson-gem')
|
@@ -17,7 +17,7 @@ if allow_local && File.exist?('../urbanopt-geojson-gem')
|
|
17
17
|
elsif allow_local
|
18
18
|
gem 'urbanopt-geojson', github: 'URBANopt/urbanopt-geojson-gem', branch: 'develop'
|
19
19
|
else
|
20
|
-
gem 'urbanopt-geojson', '~> 0.
|
20
|
+
gem 'urbanopt-geojson', '~> 0.5.0'
|
21
21
|
end
|
22
22
|
|
23
23
|
if allow_local && File.exist?('../urbanopt-reporting-gem')
|
@@ -25,8 +25,8 @@ if allow_local && File.exist?('../urbanopt-reporting-gem')
|
|
25
25
|
elsif allow_local
|
26
26
|
gem 'urbanopt-reporting', github: 'URBANopt/urbanopt-reporting-gem', branch: 'develop'
|
27
27
|
else
|
28
|
-
gem 'urbanopt-reporting', '~> 0.2
|
28
|
+
gem 'urbanopt-reporting', '~> 0.3.2'
|
29
29
|
end
|
30
30
|
|
31
31
|
# include the honeybee-openstudio-gem
|
32
|
-
gem 'honeybee-openstudio', '2.
|
32
|
+
gem 'honeybee-openstudio', '2.10.3'
|
@@ -60,6 +60,19 @@ class FromHoneybeeModel < OpenStudio::Measure::ModelMeasure
|
|
60
60
|
model_json.setDisplayName('Path to the Honeybee Model JSON file')
|
61
61
|
args << model_json
|
62
62
|
|
63
|
+
# Make an argument for schedule csv dir
|
64
|
+
schedule_csv_dir = OpenStudio::Measure::OSArgument.makeStringArgument('schedule_csv_dir', false)
|
65
|
+
schedule_csv_dir.setDisplayName('Directory for exported CSV Schedules')
|
66
|
+
schedule_csv_dir.setDescription('If set, Fixed Interval Schedules will be translated to CSV Schedules in this directory')
|
67
|
+
schedule_csv_dir.setDefaultValue('')
|
68
|
+
args << schedule_csv_dir
|
69
|
+
|
70
|
+
# Make an argument for include datetimes
|
71
|
+
include_datetimes = OpenStudio::Measure::OSArgument.makeBoolArgument('include_datetimes', false)
|
72
|
+
include_datetimes.setDisplayName('Include date time column in exported CSV Schedules')
|
73
|
+
include_datetimes.setDefaultValue(false)
|
74
|
+
args << include_datetimes
|
75
|
+
|
63
76
|
return args
|
64
77
|
end
|
65
78
|
|
@@ -72,6 +85,8 @@ class FromHoneybeeModel < OpenStudio::Measure::ModelMeasure
|
|
72
85
|
end
|
73
86
|
|
74
87
|
model_json = runner.getStringArgumentValue('model_json', user_arguments)
|
88
|
+
schedule_csv_dir = runner.getStringArgumentValue('schedule_csv_dir', user_arguments)
|
89
|
+
include_datetimes = runner.getBoolArgumentValue('include_datetimes', user_arguments)
|
75
90
|
|
76
91
|
if !File.exist?(model_json)
|
77
92
|
runner.registerError("Cannot find file '#{model_json}'")
|
@@ -80,6 +95,14 @@ class FromHoneybeeModel < OpenStudio::Measure::ModelMeasure
|
|
80
95
|
|
81
96
|
honeybee_model = Honeybee::Model.read_from_disk(model_json)
|
82
97
|
|
98
|
+
if schedule_csv_dir && !schedule_csv_dir.empty?
|
99
|
+
if !Dir.exist?(schedule_csv_dir)
|
100
|
+
runner.registerError("Directory for exported CSV Schedules does not exist '#{schedule_csv_dir}'")
|
101
|
+
return false
|
102
|
+
end
|
103
|
+
honeybee_model.set_schedule_csv_dir(schedule_csv_dir, include_datetimes)
|
104
|
+
end
|
105
|
+
|
83
106
|
STDOUT.flush
|
84
107
|
honeybee_model.to_openstudio_model(model)
|
85
108
|
STDOUT.flush
|
data/lib/to_openstudio/model.rb
CHANGED
@@ -34,9 +34,38 @@ require 'honeybee/model'
|
|
34
34
|
require 'openstudio'
|
35
35
|
|
36
36
|
module Honeybee
|
37
|
+
|
38
|
+
def self.write_schedule_csv(schedule_csv_dir, schedule_csv)
|
39
|
+
filename = schedule_csv[:filename]
|
40
|
+
columns = schedule_csv[:columns]
|
41
|
+
if !columns.empty?
|
42
|
+
n = columns[0].size
|
43
|
+
path = File.join(schedule_csv_dir, filename)
|
44
|
+
File.open(path, 'w') do |file|
|
45
|
+
(0...n).each do |i|
|
46
|
+
row = []
|
47
|
+
columns.each do |column|
|
48
|
+
row << column[i]
|
49
|
+
end
|
50
|
+
file.puts row.join(',')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
37
56
|
class Model
|
38
57
|
|
39
58
|
attr_reader :openstudio_model
|
59
|
+
attr_reader :schedule_csv_dir, :include_datetimes, :schedule_csvs
|
60
|
+
|
61
|
+
# if a schedule csv dir is specified then ScheduleFixedIntervalAbridged objects
|
62
|
+
# will be translated to ScheduleFile objects instead of ScheduleFixedInterval
|
63
|
+
# the optional schedule_csv_include_datetimes argument controls whether schedule csv
|
64
|
+
# files include a first column of date times for verification
|
65
|
+
def set_schedule_csv_dir(schedule_csv_dir, include_datetimes = false)
|
66
|
+
@schedule_csv_dir = schedule_csv_dir
|
67
|
+
@include_datetimes = include_datetimes
|
68
|
+
end
|
40
69
|
|
41
70
|
# convert to openstudio model, clears errors and warnings
|
42
71
|
def to_openstudio_model(openstudio_model=nil, log_report=true)
|
@@ -99,7 +128,7 @@ module Honeybee
|
|
99
128
|
create_schedule_type_limits(@hash[:properties][:energy][:schedule_type_limits])
|
100
129
|
end
|
101
130
|
if @hash[:properties][:energy][:schedules]
|
102
|
-
create_schedules(@hash[:properties][:energy][:schedules])
|
131
|
+
create_schedules(@hash[:properties][:energy][:schedules], false, true)
|
103
132
|
end
|
104
133
|
|
105
134
|
if log_report
|
@@ -283,7 +312,32 @@ module Honeybee
|
|
283
312
|
end
|
284
313
|
end
|
285
314
|
|
286
|
-
def create_schedules(schedule_dicts, check_existing=false)
|
315
|
+
def create_schedules(schedule_dicts, check_existing=false, check_leap_year=true)
|
316
|
+
|
317
|
+
# clear out schedule_csvs
|
318
|
+
@schedule_csvs = {}
|
319
|
+
|
320
|
+
if check_leap_year
|
321
|
+
is_leap_year = :unknown
|
322
|
+
schedule_dicts.each do |schedule|
|
323
|
+
# set is leap year = true in case start date has 3 integers
|
324
|
+
this_leap_year = false
|
325
|
+
if schedule[:start_date] && schedule[:start_date][2]
|
326
|
+
this_leap_year = true
|
327
|
+
end
|
328
|
+
if is_leap_year == :unknown
|
329
|
+
is_leap_year = this_leap_year
|
330
|
+
elsif is_leap_year != this_leap_year
|
331
|
+
raise("Mixed leap year information.")
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
if is_leap_year != :unknown
|
336
|
+
year_description = openstudio_model.getYearDescription
|
337
|
+
year_description.setIsLeapYear(is_leap_year)
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
287
341
|
schedule_dicts.each do |schedule|
|
288
342
|
# check if there's already a schedule in the model with the identifier
|
289
343
|
add_obj = true
|
@@ -305,9 +359,15 @@ module Honeybee
|
|
305
359
|
else
|
306
360
|
raise("Unknown schedule type #{schedule_type}.")
|
307
361
|
end
|
308
|
-
schedule_object.to_openstudio(@openstudio_model)
|
362
|
+
schedule_object.to_openstudio(@openstudio_model, @schedule_csv_dir, @include_datetimes, @schedule_csvs)
|
309
363
|
end
|
310
364
|
end
|
365
|
+
|
366
|
+
# write schedule csvs
|
367
|
+
@schedule_csvs.each_value do |schedule_csv|
|
368
|
+
Honeybee.write_schedule_csv(@schedule_csv_dir, schedule_csv)
|
369
|
+
end
|
370
|
+
|
311
371
|
end
|
312
372
|
|
313
373
|
def create_program_types(program_dicts, check_existing=false)
|
@@ -343,7 +403,7 @@ module Honeybee
|
|
343
403
|
end
|
344
404
|
@@standards[:schedules].each do |schedule|
|
345
405
|
if schedule[:identifier] == 'Always On'
|
346
|
-
create_schedules([schedule], true)
|
406
|
+
create_schedules([schedule], true, false)
|
347
407
|
end
|
348
408
|
end
|
349
409
|
|
@@ -387,7 +447,7 @@ module Honeybee
|
|
387
447
|
openstudio_thermostat = thermostat_object.to_openstudio(@openstudio_model)
|
388
448
|
thermal_zone_object.setThermostatSetpointDualSetpoint(openstudio_thermostat)
|
389
449
|
if setpoint_hash[:humidifying_schedule] or setpoint_hash[:dehumidifying_schedule]
|
390
|
-
humidistat_object =
|
450
|
+
humidistat_object = SetpointHumidistat.new(setpoint_hash)
|
391
451
|
openstudio_humidistat = humidistat_object.to_openstudio(@openstudio_model)
|
392
452
|
thermal_zone_object.setZoneControlHumidistat(openstudio_humidistat)
|
393
453
|
end
|
@@ -42,26 +42,60 @@ module Honeybee
|
|
42
42
|
nil
|
43
43
|
end
|
44
44
|
|
45
|
-
def to_openstudio(openstudio_model)
|
45
|
+
def to_openstudio(openstudio_model, schedule_csv_dir = nil, include_datetimes = nil, schedule_csvs = nil)
|
46
|
+
if schedule_csv_dir
|
47
|
+
to_schedule_file(openstudio_model, schedule_csv_dir, include_datetimes, schedule_csvs)
|
48
|
+
else
|
49
|
+
to_schedule_fixed_interval(openstudio_model)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def start_month
|
54
|
+
if @hash[:start_date]
|
55
|
+
return @hash[:start_date][0]
|
56
|
+
end
|
57
|
+
defaults[:start_date][:default][0]
|
58
|
+
end
|
59
|
+
|
60
|
+
def start_day
|
61
|
+
if @hash[:start_date]
|
62
|
+
return @hash[:start_date][1]
|
63
|
+
end
|
64
|
+
defaults[:start_date][:default][1]
|
65
|
+
end
|
66
|
+
|
67
|
+
def interpolate
|
68
|
+
if @hash[:interpolate]
|
69
|
+
return @hash[:interpolate]
|
70
|
+
end
|
71
|
+
defaults[:interpolate][:default]
|
72
|
+
end
|
73
|
+
|
74
|
+
def timestep
|
75
|
+
if @hash[:timestep]
|
76
|
+
return @hash[:timestep]
|
77
|
+
end
|
78
|
+
defaults[:timestep][:default]
|
79
|
+
end
|
80
|
+
|
81
|
+
def placeholder_value
|
82
|
+
if @hash[:placeholder_value]
|
83
|
+
return @hash[:placeholder_value]
|
84
|
+
end
|
85
|
+
defaults[:placeholder_value][:default]
|
86
|
+
end
|
87
|
+
|
88
|
+
def to_schedule_fixed_interval(openstudio_model)
|
46
89
|
# create the new schedule
|
47
90
|
os_fi_schedule = OpenStudio::Model::ScheduleFixedInterval.new(openstudio_model)
|
48
91
|
os_fi_schedule.setName(@hash[:identifier])
|
49
92
|
|
50
93
|
# assign start date
|
51
|
-
|
52
|
-
|
53
|
-
os_fi_schedule.setStartDay(@hash[:start_date][1])
|
54
|
-
else
|
55
|
-
os_fi_schedule.setStartMonth(defaults[:start_date][:default][0])
|
56
|
-
os_fi_schedule.setStartDay(defaults[:start_date][:default][1])
|
57
|
-
end
|
94
|
+
os_fi_schedule.setStartMonth(start_month)
|
95
|
+
os_fi_schedule.setStartDay(start_day)
|
58
96
|
|
59
97
|
# assign the interpolate value
|
60
|
-
|
61
|
-
os_fi_schedule.setInterpolatetoTimestep(@hash[:interpolate])
|
62
|
-
else
|
63
|
-
os_fi_schedule.setInterpolatetoTimestep(defaults[:interpolate][:default])
|
64
|
-
end
|
98
|
+
os_fi_schedule.setInterpolatetoTimestep(interpolate)
|
65
99
|
|
66
100
|
# assign the schedule type limit
|
67
101
|
if @hash[:schedule_type_limit]
|
@@ -73,32 +107,114 @@ module Honeybee
|
|
73
107
|
end
|
74
108
|
|
75
109
|
# assign the timestep
|
76
|
-
|
77
|
-
|
78
|
-
interval_length = 60 / timestep
|
79
|
-
os_fi_schedule.setIntervalLength(interval_length)
|
80
|
-
else
|
81
|
-
timestep = defaults[:timestep][:default]
|
82
|
-
interval_length = 60 / timestep
|
83
|
-
os_fi_schedule.setIntervalLength(interval_length)
|
84
|
-
end
|
110
|
+
interval_length = 60 / timestep
|
111
|
+
os_fi_schedule.setIntervalLength(interval_length)
|
85
112
|
openstudio_interval_length = OpenStudio::Time.new(0, 0, interval_length)
|
86
113
|
|
87
114
|
# assign the values as a timeseries
|
88
115
|
year_description = openstudio_model.getYearDescription
|
116
|
+
start_date = year_description.makeDate(start_month, start_day)
|
117
|
+
timeseries = OpenStudio::TimeSeries.new(start_date, openstudio_interval_length, OpenStudio.createVector(@hash[:values]), '')
|
118
|
+
os_fi_schedule.setTimeSeries(timeseries)
|
89
119
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
120
|
+
os_fi_schedule
|
121
|
+
end
|
122
|
+
|
123
|
+
def to_schedule_file(openstudio_model, schedule_csv_dir, include_datetimes, schedule_csvs)
|
124
|
+
|
125
|
+
# in order to combine schedules in the same csv file they must have the same key
|
126
|
+
schedule_key = "#{@hash[:identifier]}_#{start_month}_#{start_day}_#{timestep}"
|
94
127
|
|
95
|
-
|
128
|
+
# get start and end date times
|
129
|
+
yd = openstudio_model.getYearDescription
|
130
|
+
date_time = OpenStudio::DateTime.new(yd.makeDate(1, 1), OpenStudio::Time.new(0,0,0))
|
131
|
+
start_date_time = OpenStudio::DateTime.new(yd.makeDate(start_month, start_day), OpenStudio::Time.new(0,0,0))
|
132
|
+
end_date_time = OpenStudio::DateTime.new(yd.makeDate(12, 31), OpenStudio::Time.new(1,0,0))
|
96
133
|
|
134
|
+
# get timestep
|
135
|
+
interval_length = 60 / timestep
|
136
|
+
dt = OpenStudio::Time.new(0, 0, interval_length, 0)
|
137
|
+
|
138
|
+
# get values and date times
|
97
139
|
values = @hash[:values]
|
98
|
-
|
99
|
-
|
140
|
+
num_values = values.size
|
141
|
+
i_values = 0
|
142
|
+
padded_values = []
|
143
|
+
date_times = []
|
144
|
+
pv = placeholder_value
|
100
145
|
|
101
|
-
|
146
|
+
while date_time < end_date_time
|
147
|
+
date = date_time.date
|
148
|
+
time = date_time.time
|
149
|
+
date_times << "#{date.dayOfMonth} #{date.monthOfYear.valueName} #{time.hours.to_s.rjust(2,'0')}:#{time.minutes.to_s.rjust(2,'0')}"
|
150
|
+
|
151
|
+
if date_time < start_date_time
|
152
|
+
padded_values << pv
|
153
|
+
elsif i_values < num_values
|
154
|
+
padded_values << values[i_values]
|
155
|
+
i_values += 1
|
156
|
+
else
|
157
|
+
padded_values << pv
|
158
|
+
end
|
159
|
+
|
160
|
+
date_time += dt
|
161
|
+
end
|
162
|
+
|
163
|
+
|
164
|
+
# find or create the schedule csv object which will hold the filename and columns
|
165
|
+
filename = nil
|
166
|
+
columns = nil
|
167
|
+
os_external_file = nil
|
168
|
+
schedule_csv = schedule_csvs[schedule_key]
|
169
|
+
if schedule_csv.nil?
|
170
|
+
# file name to write
|
171
|
+
filename = "#{@hash[:identifier]}.csv".gsub(' ', '_')
|
172
|
+
|
173
|
+
# columns of data
|
174
|
+
columns = []
|
175
|
+
if include_datetimes
|
176
|
+
columns << ['Date Times'].concat(date_times)
|
177
|
+
end
|
178
|
+
|
179
|
+
# schedule csv file must exist even though it has no content yet
|
180
|
+
path = File.join(schedule_csv_dir, filename)
|
181
|
+
if !File.exist?(path)
|
182
|
+
File.open(path, 'w') {|f| f.puts ''}
|
183
|
+
end
|
184
|
+
|
185
|
+
# get the external file which points to the schedule csv file
|
186
|
+
os_external_file = OpenStudio::Model::ExternalFile.getExternalFile(openstudio_model, filename)
|
187
|
+
os_external_file = os_external_file.get
|
188
|
+
|
189
|
+
schedule_csv = {filename: filename, columns: columns, os_external_file: os_external_file}
|
190
|
+
schedule_csvs[schedule_key] = schedule_csv
|
191
|
+
else
|
192
|
+
filename = schedule_csv[:filename]
|
193
|
+
columns = schedule_csv[:columns]
|
194
|
+
os_external_file = schedule_csv[:os_external_file]
|
195
|
+
end
|
196
|
+
|
197
|
+
# insert the padded_values to write later
|
198
|
+
columns << [@hash[:identifier]].concat(padded_values)
|
199
|
+
|
200
|
+
# create the schedule file
|
201
|
+
column = columns.size # 1 based index
|
202
|
+
rowsToSkip = 1
|
203
|
+
os_schedule_file = OpenStudio::Model::ScheduleFile.new(os_external_file, column, rowsToSkip)
|
204
|
+
os_schedule_file.setName(@hash[:identifier])
|
205
|
+
os_schedule_file.setInterpolatetoTimestep(interpolate)
|
206
|
+
os_schedule_file.setMinutesperItem(interval_length.to_s)
|
207
|
+
|
208
|
+
# assign the schedule type limit
|
209
|
+
if @hash[:schedule_type_limit]
|
210
|
+
schedule_type_limit = openstudio_model.getScheduleTypeLimitsByName(@hash[:schedule_type_limit])
|
211
|
+
unless schedule_type_limit.empty?
|
212
|
+
schedule_type_limit_object = schedule_type_limit.get
|
213
|
+
os_schedule_file.setScheduleTypeLimits(schedule_type_limit_object)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
os_schedule_file
|
102
218
|
end
|
103
219
|
|
104
220
|
end #ScheduleFixedIntervalAbridged
|
@@ -42,7 +42,8 @@ module Honeybee
|
|
42
42
|
nil
|
43
43
|
end
|
44
44
|
|
45
|
-
def to_openstudio(openstudio_model)
|
45
|
+
def to_openstudio(openstudio_model, schedule_csv_dir = nil, include_datetimes = nil, schedule_csvs = nil)
|
46
|
+
|
46
47
|
# create openstudio schedule ruleset object
|
47
48
|
os_sch_ruleset = OpenStudio::Model::ScheduleRuleset.new(openstudio_model)
|
48
49
|
os_sch_ruleset.setName(@hash[:identifier])
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: honeybee-openstudio
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tanushree Charan
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: exe
|
13
13
|
cert_chain: []
|
14
|
-
date:
|
14
|
+
date: 2021-01-06 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: bundler
|
@@ -117,14 +117,14 @@ dependencies:
|
|
117
117
|
requirements:
|
118
118
|
- - '='
|
119
119
|
- !ruby/object:Gem::Version
|
120
|
-
version: 0.2
|
120
|
+
version: 0.3.2
|
121
121
|
type: :runtime
|
122
122
|
prerelease: false
|
123
123
|
version_requirements: !ruby/object:Gem::Requirement
|
124
124
|
requirements:
|
125
125
|
- - '='
|
126
126
|
- !ruby/object:Gem::Version
|
127
|
-
version: 0.2
|
127
|
+
version: 0.3.2
|
128
128
|
- !ruby/object:Gem::Dependency
|
129
129
|
name: openstudio-standards
|
130
130
|
requirement: !ruby/object:Gem::Requirement
|
@@ -165,6 +165,7 @@ files:
|
|
165
165
|
- lib/files/Honeybee.rb
|
166
166
|
- lib/files/honeybee_adapter.rb
|
167
167
|
- lib/files/honeybee_workflow.osw
|
168
|
+
- lib/files/reopt_assumptions.json
|
168
169
|
- lib/files/urbanopt_Gemfile
|
169
170
|
- lib/from_openstudio.rb
|
170
171
|
- lib/from_openstudio/geometry/aperture.rb
|