urbanopt-reporting 0.4.3 → 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -1
- data/LICENSE.md +17 -17
- data/doc_templates/LICENSE.md +17 -17
- data/doc_templates/copyright_erb.txt +2 -2
- data/doc_templates/copyright_js.txt +2 -2
- data/doc_templates/copyright_ruby.txt +1 -1
- data/docs/package-lock.json +15720 -1410
- data/lib/measures/.rubocop.yml +4 -2
- data/lib/measures/default_feature_reports/measure.rb +242 -36
- data/lib/measures/export_modelica_loads/measure.rb +2 -1
- data/lib/measures/export_time_series_modelica/measure.rb +58 -59
- data/lib/measures/export_time_series_modelica/resources/os_lib_helper_methods.rb +3 -5
- data/lib/urbanopt/reporting/default_reports/construction_cost.rb +2 -1
- data/lib/urbanopt/reporting/default_reports/date.rb +2 -1
- data/lib/urbanopt/reporting/default_reports/distributed_generation.rb +24 -6
- data/lib/urbanopt/reporting/default_reports/end_use.rb +1 -1
- data/lib/urbanopt/reporting/default_reports/end_uses.rb +2 -1
- data/lib/urbanopt/reporting/default_reports/extension.rb +1 -1
- data/lib/urbanopt/reporting/default_reports/feature_report.rb +9 -8
- data/lib/urbanopt/reporting/default_reports/generator.rb +1 -2
- data/lib/urbanopt/reporting/default_reports/location.rb +2 -1
- data/lib/urbanopt/reporting/default_reports/logger.rb +2 -2
- data/lib/urbanopt/reporting/default_reports/power_distribution.rb +22 -6
- data/lib/urbanopt/reporting/default_reports/program.rb +2 -1
- data/lib/urbanopt/reporting/default_reports/reporting_period.rb +47 -7
- data/lib/urbanopt/reporting/default_reports/scenario_power_distribution.rb +148 -0
- data/lib/urbanopt/reporting/default_reports/scenario_report.rb +20 -14
- data/lib/urbanopt/reporting/default_reports/schema/scenario_csv_columns.txt +24 -0
- data/lib/urbanopt/reporting/default_reports/schema/scenario_schema.json +265 -6
- data/lib/urbanopt/reporting/default_reports/solar_pv.rb +42 -3
- data/lib/urbanopt/reporting/default_reports/storage.rb +1 -1
- data/lib/urbanopt/reporting/default_reports/thermal_storage.rb +1 -1
- data/lib/urbanopt/reporting/default_reports/timeseries_csv.rb +2 -1
- data/lib/urbanopt/reporting/default_reports/validator.rb +1 -1
- data/lib/urbanopt/reporting/default_reports/wind.rb +11 -2
- data/lib/urbanopt/reporting/default_reports.rb +1 -1
- data/lib/urbanopt/reporting/derived_extension.rb +1 -1
- data/lib/urbanopt/reporting/version.rb +2 -2
- data/lib/urbanopt/reporting.rb +1 -1
- data/urbanopt-reporting-gem.gemspec +3 -4
- metadata +16 -15
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
2
|
+
# URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -40,11 +40,10 @@
|
|
40
40
|
|
41
41
|
require 'erb'
|
42
42
|
|
43
|
-
|
44
43
|
# This measure is originally from https://github.com/urbanopt/DES_HVAC
|
45
44
|
# start the measure
|
46
45
|
class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
|
47
|
-
Dir[File.dirname(__FILE__)
|
46
|
+
Dir["#{File.dirname(__FILE__)}/resources/*.rb"].sort.each { |file| require file }
|
48
47
|
include OsLib_HelperMethods
|
49
48
|
# human readable name
|
50
49
|
def name
|
@@ -75,12 +74,12 @@ class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
|
|
75
74
|
hhw_loop_name.setDefaultValue('hot')
|
76
75
|
args << hhw_loop_name
|
77
76
|
|
78
|
-
|
77
|
+
chw_loop_name = OpenStudio::Measure::OSArgument.makeStringArgument('chw_loop_name', true)
|
79
78
|
chw_loop_name.setDisplayName('Name or Partial Name of Chilled Water Loop, non-case-sensitive')
|
80
79
|
chw_loop_name.setDefaultValue('chilled')
|
81
80
|
args << chw_loop_name
|
82
81
|
|
83
|
-
|
82
|
+
dec_places_mass_flow = OpenStudio::Measure::OSArgument.makeIntegerArgument('dec_places_mass_flow', true)
|
84
83
|
dec_places_mass_flow.setDisplayName('Number of Decimal Places to Round Mass Flow Rate')
|
85
84
|
dec_places_mass_flow.setDescription('Number of decimal places to which mass flow rate will be rounded')
|
86
85
|
dec_places_mass_flow.setDefaultValue(3)
|
@@ -113,11 +112,11 @@ class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
|
|
113
112
|
# use the built-in error checking
|
114
113
|
return false unless runner.validateUserArguments(arguments(model), user_arguments)
|
115
114
|
|
116
|
-
|
115
|
+
# #Read in argumetns related to variables for output requests
|
117
116
|
hhw_loop_name = runner.getStringArgumentValue('hhw_loop_name', user_arguments)
|
118
117
|
chw_loop_name = runner.getStringArgumentValue('chw_loop_name', user_arguments)
|
119
118
|
|
120
|
-
#Identify key names for output variables.
|
119
|
+
# Identify key names for output variables.
|
121
120
|
plantloops = model.getPlantLoops
|
122
121
|
|
123
122
|
selected_plant_loops = []
|
@@ -128,19 +127,19 @@ class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
|
|
128
127
|
reporting_frequency = 'timestep'
|
129
128
|
|
130
129
|
plantloops.each do |plantLoop|
|
131
|
-
|
130
|
+
log "plant loop name #{plantLoop.name.get}"
|
132
131
|
if plantLoop.name.get.to_s.downcase.include? chw_loop_name.to_s
|
133
|
-
#Extract plant loop information
|
134
|
-
selected_plant_loops[0]=plantLoop
|
132
|
+
# Extract plant loop information
|
133
|
+
selected_plant_loops[0] = plantLoop
|
135
134
|
key_value_chw_outlet = selected_plant_loops[0].demandOutletNode.name.to_s
|
136
135
|
key_value_chw_inlet = selected_plant_loops[0].demandInletNode.name.to_s
|
137
136
|
result << OpenStudio::IdfObject.load("Output:Variable,#{key_value_chw_outlet},#{variable_name2},timestep;").get
|
138
137
|
result << OpenStudio::IdfObject.load("Output:Variable,#{key_value_chw_inlet},#{variable_name2},timestep;").get
|
139
138
|
result << OpenStudio::IdfObject.load("Output:Variable,#{key_value_chw_outlet},#{variable_name1},timestep;").get
|
140
139
|
end
|
141
|
-
if plantLoop.name.get.to_s.downcase.include?
|
142
|
-
#Extract plant loop information
|
143
|
-
selected_plant_loops[1]=plantLoop
|
140
|
+
if plantLoop.name.get.to_s.downcase.include?(hhw_loop_name.to_s) && !plantLoop.name.get.to_s.downcase.include?('service') && !plantLoop.name.get.to_s.downcase.include?('domestic')
|
141
|
+
# Extract plant loop information
|
142
|
+
selected_plant_loops[1] = plantLoop
|
144
143
|
key_value_hhw_outlet = selected_plant_loops[1].demandOutletNode.name.to_s
|
145
144
|
key_value_hhw_inlet = selected_plant_loops[1].demandInletNode.name.to_s
|
146
145
|
result << OpenStudio::IdfObject.load("Output:Variable,#{key_value_hhw_outlet},#{variable_name2},timestep;").get
|
@@ -153,7 +152,7 @@ class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
|
|
153
152
|
result << OpenStudio::IdfObject.load('Output:Variable,,Site Outdoor Air Drybulb Temperature,hourly;').get
|
154
153
|
result << OpenStudio::IdfObject.load('Output:Variable,,Site Outdoor Air Relative Humidity,hourly;').get
|
155
154
|
result << OpenStudio::IdfObject.load('Output:Meter,Cooling:Electricity,hourly;').get
|
156
|
-
|
155
|
+
result << OpenStudio::IdfObject.load('Output:Meter,Electricity:Facility,timestep;').get # #Using this for data at timestep interval
|
157
156
|
result << OpenStudio::IdfObject.load('Output:Meter,Heating:Electricity,hourly;').get
|
158
157
|
result << OpenStudio::IdfObject.load('Output:Meter,Heating:NaturalGas,hourly;').get
|
159
158
|
result << OpenStudio::IdfObject.load('Output:Meter,InteriorLights:Electricity,hourly;').get
|
@@ -171,15 +170,15 @@ class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
|
|
171
170
|
result
|
172
171
|
end
|
173
172
|
|
174
|
-
def extract_timeseries_into_matrix(sqlfile, data, variable_name, str, key_value = nil, default_if_empty = 0,dec_places, timestep)
|
173
|
+
def extract_timeseries_into_matrix(sqlfile, data, variable_name, str, key_value = nil, default_if_empty = 0, dec_places, timestep)
|
175
174
|
log "Executing query for #{variable_name}"
|
176
|
-
#column_name = variable_name
|
175
|
+
# column_name = variable_name
|
177
176
|
if key_value
|
178
177
|
ts = sqlfile.timeSeries('RUN PERIOD 1', 'Zone Timestep', variable_name, key_value)
|
179
|
-
#column_name += "_#{key_value}"
|
180
|
-
|
178
|
+
# column_name += "_#{key_value}"
|
179
|
+
column_name = str
|
181
180
|
else
|
182
|
-
#ts = sqlfile.timeSeries('RUN PERIOD 1', 'Hourly', variable_name)
|
181
|
+
# ts = sqlfile.timeSeries('RUN PERIOD 1', 'Hourly', variable_name)
|
183
182
|
ts = sqlfile.timeSeries('RUN PERIOD 1', 'Zone Timestep', variable_name)
|
184
183
|
end
|
185
184
|
log 'Iterating over timeseries'
|
@@ -201,16 +200,16 @@ class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
|
|
201
200
|
# end
|
202
201
|
|
203
202
|
quick_proc = ts.values.to_s.split(',')
|
204
|
-
quick_proc[0]=quick_proc[0].split('(', 2).last #cleanup necessary to remove opening paren
|
205
|
-
quick_proc=quick_proc.map(&:to_f)
|
203
|
+
quick_proc[0] = quick_proc[0].split('(', 2).last # cleanup necessary to remove opening paren
|
204
|
+
quick_proc = quick_proc.map(&:to_f)
|
206
205
|
x = 0
|
207
206
|
len = quick_proc.length
|
208
|
-
|
209
|
-
while
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
207
|
+
log "quick proc #{quick_proc}"
|
208
|
+
while x < len # Round to the # of decimal places specified
|
209
|
+
quick_proc[x] = (quick_proc[x]).round(dec_places)
|
210
|
+
x += 1
|
211
|
+
end
|
212
|
+
quick_proc = quick_proc.map(&:to_s)
|
214
213
|
|
215
214
|
# the first and last have some cleanup items because of the Vector method
|
216
215
|
quick_proc[0] = quick_proc[0].gsub(/^.*\(/, '')
|
@@ -232,7 +231,7 @@ class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
|
|
232
231
|
log "Finished extracting #{variable_name}"
|
233
232
|
end
|
234
233
|
|
235
|
-
def create_new_variable_sum(data, new_var_name, include_str, options=nil)
|
234
|
+
def create_new_variable_sum(data, new_var_name, include_str, options = nil)
|
236
235
|
var_info = {
|
237
236
|
name: new_var_name,
|
238
237
|
var_indexes: []
|
@@ -285,16 +284,18 @@ class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
|
|
285
284
|
|
286
285
|
# lookup and replace argument values from upstream measures
|
287
286
|
if args['use_upstream_args'] == true
|
288
|
-
args.each do |arg,value|
|
287
|
+
args.each do |arg, value|
|
289
288
|
next if arg == 'use_upstream_args' # this argument should not be changed
|
289
|
+
|
290
290
|
value_from_osw = OsLib_HelperMethods.check_upstream_measure_for_arg(runner, arg)
|
291
291
|
if !value_from_osw.empty?
|
292
292
|
runner.registerInfo("Replacing argument named #{arg} from current measure with a value of #{value_from_osw[:value]} from #{value_from_osw[:measure_name]}.")
|
293
293
|
new_val = value_from_osw[:value]
|
294
294
|
# TODO: make code to handle non strings more robust. check_upstream_measure_for_arg could pass back the argument type
|
295
|
-
|
295
|
+
case arg
|
296
|
+
when 'hhw_loop_name'
|
296
297
|
args[arg] = new_val.to_s
|
297
|
-
|
298
|
+
when 'chw_loop_name'
|
298
299
|
args[arg] = new_val.to_s
|
299
300
|
else
|
300
301
|
args[arg] = new_val
|
@@ -314,8 +315,8 @@ class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
|
|
314
315
|
end
|
315
316
|
model = model.get
|
316
317
|
|
317
|
-
timesteps_per_hour=model.getTimestep.numberOfTimestepsPerHour.to_i
|
318
|
-
timestep=60/timesteps_per_hour #timestep in minutes
|
318
|
+
timesteps_per_hour = model.getTimestep.numberOfTimestepsPerHour.to_i
|
319
|
+
timestep = 60 / timesteps_per_hour # timestep in minutes
|
319
320
|
|
320
321
|
sqlFile = runner.lastEnergyPlusSqlFile
|
321
322
|
if sqlFile.empty?
|
@@ -342,7 +343,7 @@ class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
|
|
342
343
|
ts = sqlFile.timeSeries('RUN PERIOD 1', 'Zone Timestep', attribute_name)
|
343
344
|
if ts.empty?
|
344
345
|
runner.registerError("This feature does not have the attribute '#{attribute_name}' to enable this measure to work." \
|
345
|
-
|
346
|
+
'To resolve, simulate a building with electricity or remove this measure from your workflow.')
|
346
347
|
else
|
347
348
|
ts = ts.first
|
348
349
|
dt_base = nil
|
@@ -357,7 +358,7 @@ class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
|
|
357
358
|
dt.date.dayOfWeek.value,
|
358
359
|
dt.time.hours,
|
359
360
|
dt.time.minutes,
|
360
|
-
dt_current.to_time.to_i - dt_base.to_time.to_i + timestep*60
|
361
|
+
dt_current.to_time.to_i - dt_base.to_time.to_i + timestep * 60
|
361
362
|
]
|
362
363
|
end
|
363
364
|
end
|
@@ -367,52 +368,51 @@ class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
|
|
367
368
|
selected_plant_loops = []
|
368
369
|
i = 0
|
369
370
|
|
370
|
-
key_var={}
|
371
|
+
key_var = {}
|
371
372
|
|
372
373
|
plantloops.each do |plantLoop|
|
373
374
|
if plantLoop.name.get.to_s.downcase.include? chw_loop_name.to_str
|
374
|
-
#Extract plant loop information
|
375
|
-
|
375
|
+
# Extract plant loop information
|
376
|
+
selected_plant_loops[0] = plantLoop
|
376
377
|
end
|
377
378
|
if plantLoop.name.get.to_s.downcase.include? hhw_loop_name.to_str
|
378
|
-
|
379
|
-
|
379
|
+
# Get plant loop information
|
380
|
+
selected_plant_loops[1] = plantLoop
|
380
381
|
end
|
381
382
|
end
|
382
383
|
|
383
384
|
if !selected_plant_loops[1].nil?
|
384
|
-
#Set up variables for output
|
385
|
+
# Set up variables for output
|
385
386
|
key_value_hhw_outlet = selected_plant_loops[1].demandOutletNode.name.to_s
|
386
387
|
key_value_hhw_inlet = selected_plant_loops[1].demandInletNode.name.to_s
|
387
|
-
key_var['hhw_outlet_massflow']='massFlowRateHeating'
|
388
|
-
key_var['hhw_outlet_temp']='heatingReturnTemperature[C]'
|
389
|
-
key_var['hhw_inlet_temp']='heatingSupplyTemperature[C]'
|
390
|
-
#Extract time series
|
388
|
+
key_var['hhw_outlet_massflow'] = 'massFlowRateHeating'
|
389
|
+
key_var['hhw_outlet_temp'] = 'heatingReturnTemperature[C]'
|
390
|
+
key_var['hhw_inlet_temp'] = 'heatingSupplyTemperature[C]'
|
391
|
+
# Extract time series
|
391
392
|
extract_timeseries_into_matrix(sqlFile, rows, 'System Node Temperature', key_var['hhw_outlet_temp'], key_value_hhw_outlet, 0, dec_places_temp, timestep)
|
392
393
|
extract_timeseries_into_matrix(sqlFile, rows, 'System Node Temperature', key_var['hhw_inlet_temp'], key_value_hhw_inlet, 0, dec_places_temp, timestep)
|
393
394
|
extract_timeseries_into_matrix(sqlFile, rows, 'System Node Mass Flow Rate', key_var['hhw_outlet_massflow'], key_value_hhw_outlet, 0, dec_places_mass_flow, timestep)
|
394
395
|
else
|
395
|
-
runner.registerWarning(
|
396
|
+
runner.registerWarning('No hot water loop found. If one is expected, make sure the hot water loop name argument provides a string present in its name.')
|
396
397
|
end
|
397
398
|
|
398
399
|
if !selected_plant_loops[0].nil?
|
399
|
-
#Set up variables for outputs
|
400
|
+
# Set up variables for outputs
|
400
401
|
key_value_chw_outlet = selected_plant_loops[0].demandOutletNode.name.to_s
|
401
402
|
key_value_chw_inlet = selected_plant_loops[0].demandInletNode.name.to_s
|
402
|
-
key_var['chw_outlet_massflow']='massFlowRateCooling'
|
403
|
-
key_var['chw_outlet_temp']='ChilledWaterReturnTemperature[C]'
|
404
|
-
key_var['chw_inlet_temp']='ChilledWaterSupplyTemperature[C]'
|
405
|
-
#Extract time series
|
406
|
-
extract_timeseries_into_matrix(sqlFile, rows, 'System Node Temperature', key_var['chw_outlet_temp'], key_value_chw_outlet, 0, dec_places_temp,timestep)
|
407
|
-
extract_timeseries_into_matrix(sqlFile, rows, 'System Node Temperature', key_var['chw_inlet_temp'], key_value_chw_inlet, 0, dec_places_temp,timestep)
|
408
|
-
extract_timeseries_into_matrix(sqlFile, rows, 'System Node Mass Flow Rate', key_var['chw_outlet_massflow'], key_value_chw_outlet, 0, dec_places_mass_flow,timestep)
|
403
|
+
key_var['chw_outlet_massflow'] = 'massFlowRateCooling'
|
404
|
+
key_var['chw_outlet_temp'] = 'ChilledWaterReturnTemperature[C]'
|
405
|
+
key_var['chw_inlet_temp'] = 'ChilledWaterSupplyTemperature[C]'
|
406
|
+
# Extract time series
|
407
|
+
extract_timeseries_into_matrix(sqlFile, rows, 'System Node Temperature', key_var['chw_outlet_temp'], key_value_chw_outlet, 0, dec_places_temp, timestep)
|
408
|
+
extract_timeseries_into_matrix(sqlFile, rows, 'System Node Temperature', key_var['chw_inlet_temp'], key_value_chw_inlet, 0, dec_places_temp, timestep)
|
409
|
+
extract_timeseries_into_matrix(sqlFile, rows, 'System Node Mass Flow Rate', key_var['chw_outlet_massflow'], key_value_chw_outlet, 0, dec_places_mass_flow, timestep)
|
409
410
|
else
|
410
|
-
runner.registerWarning(
|
411
|
+
runner.registerWarning('No chilled water loop found. If one is expected, make sure the chilled water loop name argument provides a string present in its name.')
|
411
412
|
end
|
412
413
|
|
413
|
-
|
414
|
-
|
415
|
-
runner.registerWarning("No HVAC plant loops found. If one or more plant loops are expected, make sure they follow the naming conventions mentioned in the previous warnings.")
|
414
|
+
if selected_plant_loops[0].nil? && selected_plant_loops[1].nil?
|
415
|
+
runner.registerWarning('No HVAC plant loops found. If one or more plant loops are expected, make sure they follow the naming conventions mentioned in the previous warnings.')
|
416
416
|
end
|
417
417
|
|
418
418
|
if !selected_plant_loops.nil?
|
@@ -430,6 +430,5 @@ class ExportTimeSeriesLoadsCSV < OpenStudio::Measure::ReportingMeasure
|
|
430
430
|
end
|
431
431
|
end
|
432
432
|
|
433
|
-
|
434
433
|
# register the measure to be used by the application
|
435
434
|
ExportTimeSeriesLoadsCSV.new.registerWithApplication
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
2
|
+
# URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -358,10 +358,8 @@ module OsLib_HelperMethods
|
|
358
358
|
objectArray.each do |object|
|
359
359
|
object_LCCs = object.lifeCycleCosts
|
360
360
|
object_LCCs.each do |object_LCC|
|
361
|
-
if object_LCC.category == category
|
362
|
-
|
363
|
-
counter += object_LCC.totalCost
|
364
|
-
end
|
361
|
+
if object_LCC.category == category && (onlyYearFromStartZero == false || object_LCC.yearsFromStart == 0)
|
362
|
+
counter += object_LCC.totalCost
|
365
363
|
end
|
366
364
|
end
|
367
365
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
2
|
+
# URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -50,6 +50,7 @@ module URBANopt
|
|
50
50
|
##
|
51
51
|
class ConstructionCost
|
52
52
|
attr_accessor :category, :item_name, :unit_cost, :cost_units, :item_quantity, :total_cost # :nodoc:
|
53
|
+
|
53
54
|
##
|
54
55
|
# ConstructionCost class intialize all construction_cost attributes:
|
55
56
|
# +:category+ , +:item_name+ , +:unit_cost+ , +:cost_units+ , +:item_quantity+ , +:total_cost+
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
2
|
+
# URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -50,6 +50,7 @@ module URBANopt
|
|
50
50
|
##
|
51
51
|
class Date
|
52
52
|
attr_accessor :month, :day_of_month, :year #:nodoc:
|
53
|
+
|
53
54
|
##
|
54
55
|
# Date class intialize all date attributes:
|
55
56
|
# +:month+ , +:day_of_month+ , +:year+
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
2
|
+
# URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -192,6 +192,15 @@ module URBANopt
|
|
192
192
|
#
|
193
193
|
attr_accessor :probs_of_surviving_by_hour_of_the_day
|
194
194
|
|
195
|
+
##
|
196
|
+
# _String_ - Filepath of reopt assumptions file used, if known
|
197
|
+
attr_accessor :reopt_assumptions_file_path
|
198
|
+
|
199
|
+
##
|
200
|
+
# _Float_ - Annual percentage of electricity supplied by renewable sources
|
201
|
+
#
|
202
|
+
attr_accessor :annual_renewable_electricity_pct
|
203
|
+
|
195
204
|
##
|
196
205
|
# Initialize distributed generation system design and financial metrics.
|
197
206
|
#
|
@@ -206,6 +215,7 @@ module URBANopt
|
|
206
215
|
def initialize(hash = {})
|
207
216
|
hash.delete_if { |k, v| v.nil? }
|
208
217
|
|
218
|
+
@annual_renewable_electricity_pct = hash[:annual_renewable_electricity_pct]
|
209
219
|
@lcc_us_dollars = hash[:lcc_us_dollars]
|
210
220
|
@lcc_bau_us_dollars = hash[:lcc_bau_us_dollars]
|
211
221
|
@npv_us_dollars = hash[:npv_us_dollars]
|
@@ -227,6 +237,12 @@ module URBANopt
|
|
227
237
|
@probs_of_surviving_by_month = hash[:probs_of_surviving_by_month]
|
228
238
|
@probs_of_surviving_by_hour_of_the_day = hash[:probs_of_surviving_by_hour_of_the_day]
|
229
239
|
|
240
|
+
# optional
|
241
|
+
@reopt_assumptions_file_path = nil
|
242
|
+
if hash[:reopt_assumptions_file_path]
|
243
|
+
@reopt_assumptions_file_path = hash[:reopt_assumptions_file_path]
|
244
|
+
end
|
245
|
+
|
230
246
|
@total_solar_pv_kw = nil
|
231
247
|
@total_wind_kw = nil
|
232
248
|
@total_generator_kw = nil
|
@@ -234,7 +250,7 @@ module URBANopt
|
|
234
250
|
@total_storage_kwh = nil
|
235
251
|
|
236
252
|
@solar_pv = []
|
237
|
-
if hash[:solar_pv].
|
253
|
+
if hash[:solar_pv].instance_of?(Hash)
|
238
254
|
hash[:solar_pv] = [hash[:solar_pv]]
|
239
255
|
elsif hash[:solar_pv].nil?
|
240
256
|
hash[:solar_pv] = []
|
@@ -252,7 +268,7 @@ module URBANopt
|
|
252
268
|
end
|
253
269
|
|
254
270
|
@wind = []
|
255
|
-
if hash[:wind].
|
271
|
+
if hash[:wind].instance_of?(Hash)
|
256
272
|
hash[:wind] = [hash[:wind]]
|
257
273
|
elsif hash[:wind].nil?
|
258
274
|
hash[:wind] = []
|
@@ -270,7 +286,7 @@ module URBANopt
|
|
270
286
|
end
|
271
287
|
|
272
288
|
@generator = []
|
273
|
-
if hash[:generator].
|
289
|
+
if hash[:generator].instance_of?(Hash)
|
274
290
|
hash[:generator] = [hash[:generator]]
|
275
291
|
elsif hash[:generator].nil?
|
276
292
|
hash[:generator] = []
|
@@ -288,7 +304,7 @@ module URBANopt
|
|
288
304
|
end
|
289
305
|
|
290
306
|
@storage = []
|
291
|
-
if hash[:storage].
|
307
|
+
if hash[:storage].instance_of?(Hash)
|
292
308
|
hash[:storage] = [hash[:storage]]
|
293
309
|
elsif hash[:storage].nil?
|
294
310
|
hash[:storage] = []
|
@@ -363,7 +379,8 @@ module URBANopt
|
|
363
379
|
##
|
364
380
|
def to_hash
|
365
381
|
result = {}
|
366
|
-
|
382
|
+
result[:reopt_assumptions_file_path] = @reopt_assumptions_file_path if @reopt_assumptions_file_path
|
383
|
+
result[:annual_renewable_electricity_pct] = @annual_renewable_electricity_pct if @annual_renewable_electricity_pct
|
367
384
|
result[:lcc_us_dollars] = @lcc_us_dollars if @lcc_us_dollars
|
368
385
|
result[:lcc_bau_us_dollars] = @lcc_bau_us_dollars if @lcc_bau_us_dollars
|
369
386
|
result[:npv_us_dollars] = @npv_us_dollars if @npv_us_dollars
|
@@ -433,6 +450,7 @@ module URBANopt
|
|
433
450
|
# Merge a distributed generation system with a new system
|
434
451
|
##
|
435
452
|
def self.merge_distributed_generation(existing_dgen, new_dgen)
|
453
|
+
existing_dgen.annual_renewable_electricity_pct = add_values(existing_dgen.annual_renewable_electricity_pct, new_dgen.annual_renewable_electricity_pct)
|
436
454
|
existing_dgen.lcc_us_dollars = add_values(existing_dgen.lcc_us_dollars, new_dgen.lcc_us_dollars)
|
437
455
|
existing_dgen.lcc_bau_us_dollars = add_values(existing_dgen.lcc_bau_us_dollars, new_dgen.lcc_bau_us_dollars)
|
438
456
|
existing_dgen.npv_us_dollars = add_values(existing_dgen.npv_us_dollars, new_dgen.npv_us_dollars)
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
2
|
+
# URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
2
|
+
# URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -50,6 +50,7 @@ module URBANopt
|
|
50
50
|
##
|
51
51
|
class EndUses
|
52
52
|
attr_accessor :electricity_kwh, :natural_gas_kwh, :propane_kwh, :fuel_oil_kwh, :other_fuels_kwh, :district_cooling_kwh, :district_heating_kwh, :water_qbft # :nodoc:
|
53
|
+
|
53
54
|
##
|
54
55
|
# EndUses class intialize end_uses(fuel type) attributes: +:electricity_kwh+ , +:natural_gas_kwh+ , +:propane_kwh+ , +:fuel_oil_kwh+ , +:other_fuels_kwh+ ,
|
55
56
|
# +:district_cooling_kwh+ , +:district_heating_kwh+ , +:water_qbft+
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
2
|
+
# URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
2
|
+
# URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -65,6 +65,7 @@ module URBANopt
|
|
65
65
|
class FeatureReport
|
66
66
|
attr_accessor :id, :name, :directory_name, :feature_type, :timesteps_per_hour, :simulation_status,
|
67
67
|
:timeseries_csv, :location, :program, :design_parameters, :construction_costs, :reporting_periods, :distributed_generation, :power_distribution, :thermal_storage # :nodoc:
|
68
|
+
|
68
69
|
##
|
69
70
|
# Each FeatureReport object corresponds to a single Feature.
|
70
71
|
##
|
@@ -254,15 +255,15 @@ module URBANopt
|
|
254
255
|
# create feature reports directory
|
255
256
|
Dir.mkdir(results_dir_path) unless Dir.exist?(File.join(@directory_name, 'feature_reports'))
|
256
257
|
|
257
|
-
@timeseries_csv.path = File.join(@directory_name, 'feature_reports', file_name
|
258
|
+
@timeseries_csv.path = File.join(@directory_name, 'feature_reports', "#{file_name}.csv")
|
258
259
|
FileUtils.mkdir_p File.dirname(@timeseries_csv.path)
|
259
260
|
@timeseries_csv.save_data
|
260
261
|
|
261
|
-
## save json
|
262
|
+
## save json report
|
262
263
|
# feature_hash
|
263
264
|
feature_hash = to_hash
|
264
265
|
|
265
|
-
json_name_path = File.join(results_dir_path, file_name
|
266
|
+
json_name_path = File.join(results_dir_path, "#{file_name}.json")
|
266
267
|
|
267
268
|
File.open(json_name_path, 'w') do |f|
|
268
269
|
f.puts JSON.pretty_generate(feature_hash)
|
@@ -277,7 +278,7 @@ module URBANopt
|
|
277
278
|
if !old_timeseries_path.nil?
|
278
279
|
@timeseries_csv.path = old_timeseries_path
|
279
280
|
else
|
280
|
-
@timeseries_csv.path = File.join(@directory_name, file_name
|
281
|
+
@timeseries_csv.path = File.join(@directory_name, "#{file_name}.csv")
|
281
282
|
end
|
282
283
|
|
283
284
|
return true
|
@@ -312,7 +313,7 @@ module URBANopt
|
|
312
313
|
# feature_hash
|
313
314
|
feature_hash = to_hash
|
314
315
|
|
315
|
-
json_name_path = File.join(results_dir_path, file_name
|
316
|
+
json_name_path = File.join(results_dir_path, "#{file_name}.json")
|
316
317
|
|
317
318
|
File.open(json_name_path, 'w') do |f|
|
318
319
|
f.puts JSON.pretty_generate(feature_hash)
|
@@ -327,7 +328,7 @@ module URBANopt
|
|
327
328
|
|
328
329
|
##
|
329
330
|
# Saves the 'default_feature_report.csv' file to the results directory
|
330
|
-
# This method only copies the CSV feature reports from the folder generated by the reporting measure
|
331
|
+
# This method only copies the CSV feature reports from the folder generated by the reporting measure
|
331
332
|
# (<meausure number>_default_feature_reports/) to the new feature_reports/ folder
|
332
333
|
##
|
333
334
|
# [parameters]:
|
@@ -347,7 +348,7 @@ module URBANopt
|
|
347
348
|
# copy the CSV report to the new feature_reports folder
|
348
349
|
directory_folders.each do |f|
|
349
350
|
if f.include? '_default_feature_reports'
|
350
|
-
FileUtils.cp(File.join(f, 'default_feature_reports.csv'), File.join(results_dir_path, @file_name
|
351
|
+
FileUtils.cp(File.join(f, 'default_feature_reports.csv'), File.join(results_dir_path, "#{@file_name}.csv"))
|
351
352
|
end
|
352
353
|
end
|
353
354
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
2
|
+
# URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -80,7 +80,6 @@ module URBANopt
|
|
80
80
|
result = {}
|
81
81
|
|
82
82
|
result[:size_kw] = @size_kw if @size_kw
|
83
|
-
|
84
83
|
return result
|
85
84
|
end
|
86
85
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
2
|
+
# URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -50,6 +50,7 @@ module URBANopt
|
|
50
50
|
##
|
51
51
|
class Location
|
52
52
|
attr_accessor :latitude_deg, :longitude_deg, :surface_elevation_ft, :weather_filename #:nodoc:
|
53
|
+
|
53
54
|
##
|
54
55
|
# Location class initialize location attributes: +:latitude_deg+ , +:longitude_deg+ , +:surface_elevation_ft+ , +:weather_filename+
|
55
56
|
##
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
2
|
+
# URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -43,7 +43,7 @@ require 'logger'
|
|
43
43
|
module URBANopt
|
44
44
|
module Reporting
|
45
45
|
module DefaultReports
|
46
|
-
@@logger = Logger.new(
|
46
|
+
@@logger = Logger.new($stdout)
|
47
47
|
##
|
48
48
|
# Definining class variable "@@logger" to log errors, info and warning messages.
|
49
49
|
def self.logger
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
2
|
+
# URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -50,10 +50,12 @@ module URBANopt
|
|
50
50
|
# power_distributio include eletrical power distribution systems information.
|
51
51
|
##
|
52
52
|
class PowerDistribution
|
53
|
-
attr_accessor :under_voltage_hours, :over_voltage_hours
|
53
|
+
attr_accessor :under_voltage_hours, :over_voltage_hours, :nominal_capacity,
|
54
|
+
:reactance_resistance_ratio, :nominal_voltage, :max_power_kw, :max_reactive_power_kvar # :nodoc:
|
55
|
+
|
54
56
|
##
|
55
|
-
#
|
56
|
-
# +:under_voltage_hours+ , +:over_voltage_hours+
|
57
|
+
# PowerDistribution class initialize all power_distribution attributes:
|
58
|
+
# +:under_voltage_hours+ , +:over_voltage_hours+, +:nominal_capacity+, +:reactance_resistance_ratio+
|
57
59
|
##
|
58
60
|
# [parameters:]
|
59
61
|
# +hash+ - _Hash_ - A hash which may contain a deserialized power_distribution.
|
@@ -64,7 +66,11 @@ module URBANopt
|
|
64
66
|
|
65
67
|
@under_voltage_hours = hash[:under_voltage_hours]
|
66
68
|
@over_voltage_hours = hash[:over_voltage_hours]
|
67
|
-
|
69
|
+
@nominal_capacity = hash[:nominal_capacity]
|
70
|
+
@reactance_resistance_ratio = hash[:reactance_resistance_ratio]
|
71
|
+
@nominal_voltage = hash[:nominal_voltage] # in V
|
72
|
+
@max_power_kw = hash[:max_power_kw]
|
73
|
+
@max_reactive_power_kvar = hash[:max_reactive_power_kvar]
|
68
74
|
# initialize class variables @@validator and @@schema
|
69
75
|
@@validator ||= Validator.new
|
70
76
|
@@schema ||= @@validator.schema
|
@@ -77,6 +83,11 @@ module URBANopt
|
|
77
83
|
hash = {}
|
78
84
|
hash[:under_voltage_hours] = nil
|
79
85
|
hash[:over_voltage_hours] = nil
|
86
|
+
hash[:nominal_capacity] = nil
|
87
|
+
hash[:reactance_resistance_ratio] = nil
|
88
|
+
hash[:nominal_voltage] = nil
|
89
|
+
hash[:max_power_kw] = nil
|
90
|
+
hash[:max_reactive_power_kvar] = nil
|
80
91
|
|
81
92
|
return hash
|
82
93
|
end
|
@@ -91,6 +102,11 @@ module URBANopt
|
|
91
102
|
result = {}
|
92
103
|
result[:under_voltage_hours] = @under_voltage_hours if @under_voltage_hours
|
93
104
|
result[:over_voltage_hours] = @over_voltage_hours if @over_voltage_hours
|
105
|
+
result[:nominal_capacity] = @nominal_capacity if @nominal_capacity
|
106
|
+
result[:reactance_resistance_ratio] = @reactance_resistance_ratio if @reactance_resistance_ratio
|
107
|
+
result[:nominal_voltage] = @nominal_voltage if @nominal_voltage
|
108
|
+
result[:max_power_kw] = @max_power_kw if @max_power_kw
|
109
|
+
result[:max_reactive_power_kvar] = @max_reactive_power_kvar if @max_reactive_power_kvar
|
94
110
|
|
95
111
|
# validate power_distribution properties against schema
|
96
112
|
if @@validator.validate(@@schema[:definitions][:PowerDistribution][:properties], result).any?
|
@@ -104,7 +120,7 @@ module URBANopt
|
|
104
120
|
# Merges muliple power distribution results together.
|
105
121
|
##
|
106
122
|
# +new_costs+ - _Array_ - An array of ConstructionCost objects.
|
107
|
-
def
|
123
|
+
def merge_power_distribution
|
108
124
|
# method to be developed for any attributes to be aggregated or merged
|
109
125
|
end
|
110
126
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# *********************************************************************************
|
2
|
-
# URBANopt™, Copyright (c) 2019-
|
2
|
+
# URBANopt™, Copyright (c) 2019-2022, Alliance for Sustainable Energy, LLC, and other
|
3
3
|
# contributors. All rights reserved.
|
4
4
|
|
5
5
|
# Redistribution and use in source and binary forms, with or without modification,
|
@@ -56,6 +56,7 @@ module URBANopt
|
|
56
56
|
:maximum_number_of_parking_stories_above_ground, :number_of_residential_units, :building_types, :building_type, :maximum_occupancy,
|
57
57
|
:area_sqft, :window_area_sqft, :north_window_area_sqft, :south_window_area_sqft, :east_window_area_sqft, :west_window_area_sqft, :wall_area_sqft, :roof_area_sqft, :equipment_roof_area_sqft,
|
58
58
|
:photovoltaic_roof_area_sqft, :available_roof_area_sqft, :total_roof_area_sqft, :orientation_deg, :aspect_ratio, :total_construction_cost_dollar # :nodoc:
|
59
|
+
|
59
60
|
# Program class initialize building program attributes: +:site_area_sqft+ , +:floor_area_sqft+ , +:conditioned_area_sqft+ , +:unconditioned_area_sqft+ ,
|
60
61
|
# +:footprint_area_sqft+ , +:maximum_roof_height_ft, +:maximum_number_of_stories+ , +:maximum_number_of_stories_above_ground+ , +:parking_area_sqft+ ,
|
61
62
|
# +:number_of_parking_spaces+ , +:number_of_parking_spaces_charging+ , +:parking_footprint_area_sqft+ , +:maximum_parking_height_ft+ , +:maximum_number_of_parking_stories+ ,
|