urbanopt-reporting 0.3.0 → 0.3.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +44 -2
- data/docs/package-lock.json +3 -3
- data/docs/package.json +1 -1
- data/lib/measures/default_feature_reports/measure.rb +70 -15
- data/lib/measures/default_feature_reports/measure.xml +3 -3
- data/lib/measures/export_modelica_loads/LICENSE.md +27 -0
- data/lib/measures/export_modelica_loads/README.md +26 -0
- data/lib/measures/export_modelica_loads/README.md.erb +42 -0
- data/lib/measures/export_modelica_loads/docs/.gitkeep +0 -0
- data/lib/measures/export_modelica_loads/measure.rb +375 -0
- data/lib/measures/export_modelica_loads/measure.xml +92 -0
- data/lib/measures/export_modelica_loads/resources/report.html.in +13 -0
- data/lib/measures/export_time_series_modelica/LICENSE.md +1 -0
- data/lib/measures/export_time_series_modelica/README.md +59 -0
- data/lib/measures/export_time_series_modelica/README.md.erb +42 -0
- data/lib/measures/export_time_series_modelica/docs/.gitkeep +0 -0
- data/lib/measures/export_time_series_modelica/measure.rb +430 -0
- data/lib/measures/export_time_series_modelica/measure.xml +147 -0
- data/lib/measures/export_time_series_modelica/resources/os_lib_helper_methods.rb +399 -0
- data/lib/measures/export_time_series_modelica/resources/report.html.in +13 -0
- data/lib/urbanopt/reporting/default_reports/end_use.rb +39 -17
- data/lib/urbanopt/reporting/default_reports/feature_report.rb +62 -5
- data/lib/urbanopt/reporting/default_reports/reporting_period.rb +14 -2
- data/lib/urbanopt/reporting/default_reports/scenario_report.rb +10 -5
- data/lib/urbanopt/reporting/default_reports/schema/scenario_csv_columns.txt +1 -0
- data/lib/urbanopt/reporting/default_reports/schema/scenario_schema.json +27 -12
- data/lib/urbanopt/reporting/version.rb +1 -1
- data/urbanopt-reporting-gem.gemspec +1 -1
- metadata +19 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f3bd0a381b1713f28796ac103c6b193c00a87c0ab75084bb49db62654a6f2906
|
4
|
+
data.tar.gz: 8672b851b4a5c906c2954bcb42fad185044f4b89c536e545aba185dffb0afa6b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 57bf6dadcd3d1908de6e406bd0bcdf6fd3cf0141cb6858818dc440a4b3cdf1b22d740f06353112181f8d5b3db53a7bdaeb0d890dc0b4b71c6f3103c251584a74
|
7
|
+
data.tar.gz: c3602e94784b2d91499cd7dd439f7ae24131da774241b5a0e685cb60e7a3eb00fe2d9d237431fb4430ce084ba5b678cb2032a79f5734b35c2a4600d3f82f9668
|
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,51 @@
|
|
1
1
|
# URBANopt Reporting Gem
|
2
2
|
|
3
|
+
## Version 0.3.5
|
4
|
+
|
5
|
+
Date Range: 01/16/21 - 02/04/21
|
6
|
+
|
7
|
+
- Fixed [#58]( https://github.com/urbanopt/urbanopt-reporting-gem/issues/58 ), Feature report saving bug fix.
|
8
|
+
- Fixed [#60]( https://github.com/urbanopt/urbanopt-reporting-gem/issues/60 ), Added EV/ ExteriorEquipment results to csv and json reports
|
9
|
+
- Fixed [#61]( https://github.com/urbanopt/urbanopt-reporting-gem/issues/61 ), Enhance the aggregation of enduses.
|
10
|
+
|
11
|
+
|
12
|
+
## Version 0.3.4
|
13
|
+
|
14
|
+
Date Range: 01/14/21 - 01/15/21
|
15
|
+
|
16
|
+
- Fixed [#53]( https://github.com/urbanopt/urbanopt-reporting-gem/issues/53 ), Make subfolders in feature saving if necessary
|
17
|
+
- Fixed [#55]( https://github.com/urbanopt/urbanopt-reporting-gem/issues/55 ), Fix new measures
|
18
|
+
|
19
|
+
## Version 0.3.3
|
20
|
+
|
21
|
+
Date Range: 12/09/20 - 01/13/21
|
22
|
+
|
23
|
+
- Fixed [#36]( https://github.com/urbanopt/urbanopt-reporting-gem/issues/36 ), Add reporting measure for district heating/cooling system mass flow rates
|
24
|
+
- Fixed [#37]( https://github.com/urbanopt/urbanopt-reporting-gem/issues/37 ), Add EUI to default report
|
25
|
+
- Fixed [#38]( https://github.com/urbanopt/urbanopt-reporting-gem/issues/38 ), Add better error handling around convert_units
|
26
|
+
- Fixed [#43]( https://github.com/urbanopt/urbanopt-reporting-gem/issues/43 ), Add available_roof_area calculation
|
27
|
+
- Fixed [#44]( https://github.com/urbanopt/urbanopt-reporting-gem/issues/44 ), Fix coordinates order
|
28
|
+
|
29
|
+
## Version 0.3.2
|
30
|
+
|
31
|
+
Date Range: 12/07/20 - 12/08/20
|
32
|
+
|
33
|
+
- Fixed [#27]( https://github.com/urbanopt/urbanopt-reporting-gem/issues/27 ), reporting measure fails when there are no additional fuels in the model
|
34
|
+
- Fixed [#29]( https://github.com/urbanopt/urbanopt-reporting-gem/issues/29 ), restore save_feature_report function for backward compatibility
|
35
|
+
- Fixed [#32]( https://github.com/urbanopt/urbanopt-reporting-gem/issues/32 ), bump extension-gem dependency
|
36
|
+
|
37
|
+
## Version 0.3.1
|
38
|
+
|
39
|
+
Date Range: 11/26/2020 - 12/07/2020
|
40
|
+
|
41
|
+
- Fixed [#19]( https://github.com/urbanopt/urbanopt-reporting-gem/pull/19 ), check for nil values to avoid crashing unit conversion
|
42
|
+
- Fixed [#24]( https://github.com/urbanopt/urbanopt-reporting-gem/pull/24 ), Support reporting of other fuels
|
43
|
+
- Fixed [#28]( https://github.com/urbanopt/urbanopt-reporting-gem/pull/28 ), fix for other_fuels being nil and restore save_feature_report function
|
44
|
+
|
3
45
|
## Version 0.3.0
|
4
46
|
|
5
47
|
Date Range: 11/12/2020 - 11/25/2020
|
6
|
-
|
48
|
+
|
7
49
|
- Updating dependencies to support OpenStudio 3.1.0
|
8
50
|
|
9
51
|
## Version 0.2.1
|
@@ -35,4 +77,4 @@ Date Range: 08/27/2020 - 09/21/2020
|
|
35
77
|
|
36
78
|
08/17/2020
|
37
79
|
|
38
|
-
Initial release of the urbanopt-reporting gem.
|
80
|
+
Initial release of the urbanopt-reporting gem.
|
data/docs/package-lock.json
CHANGED
@@ -4814,9 +4814,9 @@
|
|
4814
4814
|
"integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ=="
|
4815
4815
|
},
|
4816
4816
|
"highlight.js": {
|
4817
|
-
"version": "10.
|
4818
|
-
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.
|
4819
|
-
"integrity": "sha512-
|
4817
|
+
"version": "10.4.1",
|
4818
|
+
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.4.1.tgz",
|
4819
|
+
"integrity": "sha512-yR5lWvNz7c85OhVAEAeFhVCc/GV4C30Fjzc/rCP0aCWzc1UUOPUk55dK/qdwTZHBvMZo+eZ2jpk62ndX/xMFlg=="
|
4820
4820
|
},
|
4821
4821
|
"hmac-drbg": {
|
4822
4822
|
"version": "1.0.1",
|
data/docs/package.json
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
},
|
11
11
|
"author": "NREL",
|
12
12
|
"dependencies": {
|
13
|
-
"highlight.js": "^10.
|
13
|
+
"highlight.js": "^10.4.1",
|
14
14
|
"json-schema-ref-parser": "^9.0.6",
|
15
15
|
"json-schema-view-js": "git+https://git@github.com/bgschiller/json-schema-view-js.git",
|
16
16
|
"vuepress": "^1.7.1",
|
@@ -165,9 +165,9 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
165
165
|
|
166
166
|
# Request the output for each end use/fuel type combination
|
167
167
|
end_uses.each do |end_use|
|
168
|
-
end_use,
|
168
|
+
end_use, = end_use
|
169
169
|
fuel_types.each do |fuel_type|
|
170
|
-
fuel_type,
|
170
|
+
fuel_type, = fuel_type
|
171
171
|
variable_name = if end_use == 'Facility'
|
172
172
|
"#{fuel_type}:#{end_use}"
|
173
173
|
else
|
@@ -178,17 +178,17 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
178
178
|
end
|
179
179
|
|
180
180
|
# OtherFuels
|
181
|
-
other_fuels = [
|
182
|
-
other_fuel_uses = [
|
183
|
-
custom_meter_facility =
|
181
|
+
other_fuels = ['FuelOil#1', 'Diesel', 'Gasoline', 'Coal', 'Steam']
|
182
|
+
other_fuel_uses = ['HeatRejection', 'Heating', 'WaterSystems', 'InteriorEquipment']
|
183
|
+
custom_meter_facility = 'Meter:Custom,OtherFuels:Facility,OtherFuel1'
|
184
184
|
other_fuel_uses.each do |end_use|
|
185
185
|
custom_meter = "Meter:Custom,#{end_use}:OtherFuels,OtherFuel1"
|
186
|
-
other_fuels.each do |other_fuel|
|
186
|
+
other_fuels.each do |other_fuel|
|
187
187
|
result << OpenStudio::IdfObject.load("Output:Meter,#{end_use}:#{other_fuel},#{reporting_frequency};").get
|
188
188
|
custom_meter_facility += ",,#{end_use}:#{other_fuel}"
|
189
189
|
custom_meter += ",,#{end_use}:#{other_fuel}"
|
190
190
|
end
|
191
|
-
custom_meter +=
|
191
|
+
custom_meter += ';'
|
192
192
|
result << OpenStudio::IdfObject.load(custom_meter).get
|
193
193
|
result << OpenStudio::IdfObject.load("Output:Meter,#{end_use}:OtherFuels,#{reporting_frequency};").get
|
194
194
|
end
|
@@ -201,6 +201,8 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
201
201
|
result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,Gas:Facility,#{reporting_frequency};").get
|
202
202
|
result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,DistrictCooling:Facility,#{reporting_frequency};").get
|
203
203
|
result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,DistrictHeating:Facility,#{reporting_frequency};").get
|
204
|
+
|
205
|
+
|
204
206
|
# result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,Cooling:Electricity,#{reporting_frequency};").get
|
205
207
|
# result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,Heating:Electricity,#{reporting_frequency};").get
|
206
208
|
# result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,InteriorLights:Electricity,#{reporting_frequency};").get
|
@@ -213,14 +215,19 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
213
215
|
# result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,WaterSystems:Gas,#{reporting_frequency};").get
|
214
216
|
# result << OpenStudio::IdfObject.load("Output:Meter:MeterFileOnly,InteriorEquipment:Gas,#{reporting_frequency};").get
|
215
217
|
result << OpenStudio::IdfObject.load('Output:Variable,*,Heating Coil Heating Rate,hourly; !- HVAC Average [W];').get
|
218
|
+
#result << OpenStudio::IdfObject.load("Output:Variable,*,Exterior Equipment:Electric Vehicles,#{reporting_frequency};").get
|
216
219
|
|
217
220
|
timeseries_data = ['District Cooling Chilled Water Rate', 'District Cooling Mass Flow Rate',
|
218
221
|
'District Cooling Inlet Temperature', 'District Cooling Outlet Temperature',
|
219
222
|
'District Heating Hot Water Rate', 'District Heating Mass Flow Rate',
|
220
223
|
'District Heating Inlet Temperature', 'District Heating Outlet Temperature', 'Cooling Coil Total Cooling Rate',
|
221
|
-
'Heating Coil Heating Rate']
|
224
|
+
'Heating Coil Heating Rate', 'ExteriorEquipment:Electricity']
|
225
|
+
|
222
226
|
|
223
227
|
tes_timeseries_data = ['Ice Thermal Storage End Fraction', 'Cooling coil Ice Thermal Storage End Fraction']
|
228
|
+
|
229
|
+
ev_timeseries_data = ['Exterior Equipment:Electric Vehicles']
|
230
|
+
|
224
231
|
timeseries_data += tes_timeseries_data
|
225
232
|
|
226
233
|
timeseries_data.each do |ts|
|
@@ -258,6 +265,11 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
258
265
|
if value.nil?
|
259
266
|
return nil
|
260
267
|
end
|
268
|
+
if from_units.nil? || to_units.nil?
|
269
|
+
@runner.registerError("Cannot convert units...from_units: #{from_units} or to_units: #{to_units} left blank.")
|
270
|
+
return nil
|
271
|
+
end
|
272
|
+
|
261
273
|
# apply unit conversion
|
262
274
|
value_converted = OpenStudio.convert(value, from_units, to_units)
|
263
275
|
if value_converted.is_initialized
|
@@ -353,10 +365,10 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
353
365
|
##
|
354
366
|
|
355
367
|
if feature_location.include? '['
|
356
|
-
# get latitude from feature_location
|
357
|
-
latitude = (feature_location.split(',')[0].delete! '[]').to_f
|
358
368
|
# get longitude from feature_location
|
359
|
-
longitude = (feature_location.split(',')[
|
369
|
+
longitude = (feature_location.split(',')[0].delete! '[]').to_f
|
370
|
+
# get latitude from feature_location
|
371
|
+
latitude = (feature_location.split(',')[1].delete! '[]').to_f
|
360
372
|
# latitude
|
361
373
|
feature_report.location.latitude_deg = latitude
|
362
374
|
# longitude
|
@@ -495,7 +507,22 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
495
507
|
total_roof_area += surface.netArea
|
496
508
|
end
|
497
509
|
end
|
498
|
-
|
510
|
+
|
511
|
+
total_roof_area_sqft = convert_units(total_roof_area, 'm^2', 'ft^2')
|
512
|
+
feature_report.program.roof_area_sqft[:total_roof_area_sqft] = total_roof_area_sqft
|
513
|
+
|
514
|
+
# available_roof_area_sqft
|
515
|
+
# RK: a more robust method should be implemented to find the available_roof_area
|
516
|
+
# assign available roof area to be a percentage of the total roof area
|
517
|
+
|
518
|
+
if building_types[0][:building_type].include? 'Single-Family Detached'
|
519
|
+
feature_report.program.roof_area_sqft[:available_roof_area_sqft] = 0.45 * total_roof_area_sqft
|
520
|
+
else
|
521
|
+
feature_report.program.roof_area_sqft[:available_roof_area_sqft] = 0.75 * total_roof_area_sqft
|
522
|
+
end
|
523
|
+
|
524
|
+
# RK: Temporary solution: assign available roof area to be equal to total roof area
|
525
|
+
# feature_report.program.roof_area_sqft[:available_roof_area_sqft] = total_roof_area_sqft
|
499
526
|
|
500
527
|
# orientation
|
501
528
|
# RK: a more robust method should be implemented to find orientation(finding main axis of the building using aspect ratio)
|
@@ -581,6 +608,22 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
581
608
|
total_source_energy = sql_query(runner, sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Site and Source Energy' AND RowName='Total Source Energy' AND ColumnName='Total Energy'")
|
582
609
|
feature_report.reporting_periods[0].total_source_energy_kwh = convert_units(total_source_energy, 'GJ', 'kWh')
|
583
610
|
|
611
|
+
# EUI is only valid with a full year of energy data
|
612
|
+
if begin_month == 1 && begin_day_of_month == 1 && end_month == 12 && end_day_of_month == 31
|
613
|
+
# calculate site EUI
|
614
|
+
site_EUI_kwh_per_m2 = feature_report.reporting_periods[0].total_site_energy_kwh / floor_area
|
615
|
+
site_EUI_kbtu_per_ft2 = convert_units(total_site_energy, 'GJ', 'kBtu') / feature_report.program.floor_area_sqft
|
616
|
+
# add site EUI to feature report
|
617
|
+
feature_report.reporting_periods[0].site_EUI_kwh_per_m2 = site_EUI_kwh_per_m2
|
618
|
+
feature_report.reporting_periods[0].site_EUI_kbtu_per_ft2 = site_EUI_kbtu_per_ft2
|
619
|
+
# calculate source EUI
|
620
|
+
source_EUI_kwh_per_m2 = feature_report.reporting_periods[0].total_source_energy_kwh / floor_area
|
621
|
+
source_EUI_kbtu_per_ft2 = convert_units(total_source_energy, 'GJ', 'kBtu') / feature_report.program.floor_area_sqft
|
622
|
+
# add source EUI to feature report
|
623
|
+
feature_report.reporting_periods[0].source_EUI_kwh_per_m2 = source_EUI_kwh_per_m2
|
624
|
+
feature_report.reporting_periods[0].source_EUI_kbtu_per_ft2 = source_EUI_kbtu_per_ft2
|
625
|
+
end
|
626
|
+
|
584
627
|
# net_site_energy
|
585
628
|
net_site_energy = sql_query(runner, sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='Site and Source Energy' AND RowName='Net Site Energy' AND ColumnName='Total Energy'")
|
586
629
|
feature_report.reporting_periods[0].net_site_energy_kwh = convert_units(net_site_energy, 'GJ', 'kWh')
|
@@ -609,7 +652,9 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
609
652
|
|
610
653
|
# other_fuels
|
611
654
|
additional_fuel = sql_query(runner, sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='End Uses' AND RowName='Total End Uses' AND ColumnName='Additional Fuel'")
|
612
|
-
|
655
|
+
# ensure additional fuel is not nil
|
656
|
+
feature_report.reporting_periods[0].other_fuels_kwh = 0.0
|
657
|
+
feature_report.reporting_periods[0].other_fuels_kwh = convert_units(additional_fuel, 'GJ', 'kWh') unless additional_fuel.nil?
|
613
658
|
feature_report.reporting_periods[0].other_fuels_kwh -= feature_report.reporting_periods[0].propane_kwh
|
614
659
|
feature_report.reporting_periods[0].other_fuels_kwh -= feature_report.reporting_periods[0].fuel_oil_kwh
|
615
660
|
|
@@ -686,18 +731,27 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
686
731
|
m = feature_report.reporting_periods[0].end_uses.send(x_u)
|
687
732
|
|
688
733
|
y = eu.tr(' ', '_').downcase
|
734
|
+
# ensure not nil so the equations below don't error out
|
735
|
+
if sql_r.nil?
|
736
|
+
sql_r = 0.0
|
737
|
+
end
|
689
738
|
sql_r = convert_units(sql_r, 'GJ', 'kWh')
|
690
739
|
if x_u == 'other_fuels_kwh'
|
691
740
|
sql_r -= feature_report.reporting_periods[0].end_uses.propane_kwh.send(y)
|
692
741
|
sql_r -= feature_report.reporting_periods[0].end_uses.fuel_oil_kwh.send(y)
|
693
742
|
end
|
694
743
|
building_types.each do |i|
|
695
|
-
sql_r = 0.0 if
|
744
|
+
sql_r = 0.0 if i[:building_type].include?('Single-Family Detached') && x_u.include?('district')
|
696
745
|
end
|
697
746
|
m.send("#{y}=", sql_r)
|
698
747
|
end
|
699
748
|
end
|
700
749
|
|
750
|
+
# add enduses subcategories
|
751
|
+
electric_vehicles = sql_query(runner, sql_file, 'AnnualBuildingUtilityPerformanceSummary', "TableName='End Uses By Subcategory' AND RowName='Exterior Equipment:Electric Vehicles' AND ColumnName='Electricity'")
|
752
|
+
puts "electric_vehicle = #{electric_vehicles}"
|
753
|
+
feature_report.reporting_periods[0].end_uses.electricity_kwh.electric_vehicles = convert_units(electric_vehicles, 'GJ', 'kWh')
|
754
|
+
|
701
755
|
### energy_production
|
702
756
|
## electricity_produced
|
703
757
|
# photovoltaic
|
@@ -761,6 +815,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
761
815
|
'InteriorLights:Electricity',
|
762
816
|
'ExteriorLights:Electricity',
|
763
817
|
'InteriorEquipment:Electricity',
|
818
|
+
'ExteriorEquipment:Electricity',
|
764
819
|
'Fans:Electricity',
|
765
820
|
'Pumps:Electricity',
|
766
821
|
'WaterSystems:Electricity',
|
@@ -844,7 +899,7 @@ class DefaultFeatureReports < OpenStudio::Measure::ReportingMeasure
|
|
844
899
|
puts " *********timeseries_name = #{timeseries_name}******************"
|
845
900
|
runner.registerInfo("TIMESERIES: #{timeseries_name}")
|
846
901
|
|
847
|
-
# get all the key values that this timeseries can be reported for (e.g. if PMV is requested for each zone)
|
902
|
+
# get all the key values that this timeseries can be reported for (e.g. if PMV is requested for each zone)
|
848
903
|
if timeseries_name.include?('OtherFuels')
|
849
904
|
key_values = sql_file.availableKeyValues('RUN PERIOD 1', 'Zone Timestep', timeseries_name.upcase)
|
850
905
|
else
|
@@ -3,8 +3,8 @@
|
|
3
3
|
<schema_version>3.0</schema_version>
|
4
4
|
<name>default_feature_reports</name>
|
5
5
|
<uid>9ee3135a-8070-4408-bfa1-b75fecf9dd4f</uid>
|
6
|
-
<version_id>
|
7
|
-
<version_modified>
|
6
|
+
<version_id>d4f5b2e2-f93d-4ce2-9c68-ed29714fdc0c</version_id>
|
7
|
+
<version_modified>20201208T230102Z</version_modified>
|
8
8
|
<xml_checksum>FB304155</xml_checksum>
|
9
9
|
<class_name>DefaultFeatureReports</class_name>
|
10
10
|
<display_name>DefaultFeatureReports</display_name>
|
@@ -153,7 +153,7 @@
|
|
153
153
|
<filename>measure.rb</filename>
|
154
154
|
<filetype>rb</filetype>
|
155
155
|
<usage_type>script</usage_type>
|
156
|
-
<checksum>
|
156
|
+
<checksum>48AEB753</checksum>
|
157
157
|
</file>
|
158
158
|
</files>
|
159
159
|
</measure>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC. All rights reserved.
|
2
|
+
|
3
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted
|
4
|
+
provided that the following conditions are met:
|
5
|
+
|
6
|
+
(1) Redistributions of source code must retain the above copyright notice, this list of conditions
|
7
|
+
and the following disclaimer.
|
8
|
+
|
9
|
+
(2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions
|
10
|
+
and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
11
|
+
|
12
|
+
(3) Neither the name of the copyright holder nor the names of any contributors may be used to endorse
|
13
|
+
or promote products derived from this software without specific prior written permission from the
|
14
|
+
respective party.
|
15
|
+
|
16
|
+
(4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other
|
17
|
+
derivative works may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar
|
18
|
+
designation without specific prior written permission from Alliance for Sustainable Energy, LLC.
|
19
|
+
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
21
|
+
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
22
|
+
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER, THE UNITED STATES GOVERNMENT,
|
23
|
+
OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
25
|
+
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
26
|
+
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
27
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
###### (Automatically generated documentation)
|
4
|
+
|
5
|
+
# Export Modelica Loads
|
6
|
+
|
7
|
+
## Description
|
8
|
+
Use the results from the EnergyPlus simulation to generate a load file for use in Modelica. This will create a MOS and a CSV file of the heating, cooling, and hot water loads.
|
9
|
+
|
10
|
+
## Modeler Description
|
11
|
+
|
12
|
+
|
13
|
+
## Measure Type
|
14
|
+
ReportingMeasure
|
15
|
+
|
16
|
+
## Taxonomy
|
17
|
+
|
18
|
+
|
19
|
+
## Arguments
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
|
24
|
+
This measure does not have any user arguments
|
25
|
+
|
26
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
<%#= README.md.erb is used to auto-generate README.md. %>
|
2
|
+
<%#= To manually maintain README.md throw away README.md.erb and manually edit README.md %>
|
3
|
+
###### (Automatically generated documentation)
|
4
|
+
|
5
|
+
# <%= name %>
|
6
|
+
|
7
|
+
## Description
|
8
|
+
<%= description %>
|
9
|
+
|
10
|
+
## Modeler Description
|
11
|
+
<%= modelerDescription %>
|
12
|
+
|
13
|
+
## Measure Type
|
14
|
+
<%= measureType %>
|
15
|
+
|
16
|
+
## Taxonomy
|
17
|
+
<%= taxonomy %>
|
18
|
+
|
19
|
+
## Arguments
|
20
|
+
|
21
|
+
<% arguments.each do |argument| %>
|
22
|
+
### <%= argument[:display_name] %>
|
23
|
+
<%= argument[:description] %>
|
24
|
+
**Name:** <%= argument[:name] %>,
|
25
|
+
**Type:** <%= argument[:type] %>,
|
26
|
+
**Units:** <%= argument[:units] %>,
|
27
|
+
**Required:** <%= argument[:required] %>,
|
28
|
+
**Model Dependent:** <%= argument[:model_dependent] %>
|
29
|
+
<% end %>
|
30
|
+
|
31
|
+
<% if arguments.size == 0 %>
|
32
|
+
<%= "This measure does not have any user arguments" %>
|
33
|
+
<% end %>
|
34
|
+
|
35
|
+
<% if outputs.size > 0 %>
|
36
|
+
## Outputs
|
37
|
+
<% output_names = [] %>
|
38
|
+
<% outputs.each do |output| %>
|
39
|
+
<% output_names << output[:display_name] %>
|
40
|
+
<% end %>
|
41
|
+
<%= output_names.join(", ") %>
|
42
|
+
<% end %>
|
File without changes
|
@@ -0,0 +1,375 @@
|
|
1
|
+
# *******************************************************************************
|
2
|
+
# OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC.
|
3
|
+
# All rights reserved.
|
4
|
+
# Redistribution and use in source and binary forms, with or without
|
5
|
+
# modification, are permitted provided that the following conditions are met:
|
6
|
+
#
|
7
|
+
# (1) Redistributions of source code must retain the above copyright notice,
|
8
|
+
# this list of conditions and the following disclaimer.
|
9
|
+
#
|
10
|
+
# (2) Redistributions in binary form must reproduce the above copyright notice,
|
11
|
+
# this list of conditions and the following disclaimer in the documentation
|
12
|
+
# and/or other materials provided with the distribution.
|
13
|
+
#
|
14
|
+
# (3) Neither the name of the copyright holder nor the names of any contributors
|
15
|
+
# may be used to endorse or promote products derived from this software without
|
16
|
+
# specific prior written permission from the respective party.
|
17
|
+
#
|
18
|
+
# (4) Other than as required in clauses (1) and (2), distributions in any form
|
19
|
+
# of modifications or other derivative works may not use the "OpenStudio"
|
20
|
+
# trademark, "OS", "os", or any other confusingly similar designation without
|
21
|
+
# specific prior written permission from Alliance for Sustainable Energy, LLC.
|
22
|
+
#
|
23
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
|
24
|
+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
25
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
26
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
|
27
|
+
# UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
|
28
|
+
# THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
29
|
+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
30
|
+
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
31
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
32
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
33
|
+
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
34
|
+
# *******************************************************************************
|
35
|
+
|
36
|
+
require 'erb'
|
37
|
+
|
38
|
+
|
39
|
+
# This measure is originally from https://github.com/urbanopt/DES_HVAC
|
40
|
+
# start the measure
|
41
|
+
class ExportModelicaLoads < OpenStudio::Measure::ReportingMeasure
|
42
|
+
# human readable name
|
43
|
+
def name
|
44
|
+
# Measure name should be the title case of the class name.
|
45
|
+
return 'Export Modelica Loads'
|
46
|
+
end
|
47
|
+
|
48
|
+
def description
|
49
|
+
return 'Use the results from the EnergyPlus simulation to generate a load file for use in Modelica. This will create a MOS and a CSV file of the heating, cooling, and hot water loads.'
|
50
|
+
end
|
51
|
+
|
52
|
+
def modeler_description
|
53
|
+
return ''
|
54
|
+
end
|
55
|
+
|
56
|
+
def log(str)
|
57
|
+
puts "#{Time.now}: #{str}"
|
58
|
+
end
|
59
|
+
|
60
|
+
def arguments(_model)
|
61
|
+
args = OpenStudio::Measure::OSArgumentVector.new
|
62
|
+
|
63
|
+
# this measure does not require any user arguments, return an empty list
|
64
|
+
return args
|
65
|
+
end
|
66
|
+
|
67
|
+
# return a vector of IdfObject's to request EnergyPlus objects needed by the run method
|
68
|
+
def energyPlusOutputRequests(runner, user_arguments)
|
69
|
+
super(runner, user_arguments)
|
70
|
+
|
71
|
+
result = OpenStudio::IdfObjectVector.new
|
72
|
+
|
73
|
+
# To use the built-in error checking we need the model...
|
74
|
+
# get the last model and sql file
|
75
|
+
model = runner.lastOpenStudioModel
|
76
|
+
if model.empty?
|
77
|
+
runner.registerError('Cannot find last model.')
|
78
|
+
return false
|
79
|
+
end
|
80
|
+
model = model.get
|
81
|
+
|
82
|
+
# use the built-in error checking
|
83
|
+
if !runner.validateUserArguments(arguments(model), user_arguments)
|
84
|
+
return false
|
85
|
+
end
|
86
|
+
|
87
|
+
result << OpenStudio::IdfObject.load('Output:Variable,,Site Mains Water Temperature,timestep;').get
|
88
|
+
result << OpenStudio::IdfObject.load('Output:Variable,,Site Outdoor Air Drybulb Temperature,timestep;').get
|
89
|
+
result << OpenStudio::IdfObject.load('Output:Variable,,Site Outdoor Air Relative Humidity,timestep;').get
|
90
|
+
result << OpenStudio::IdfObject.load('Output:Meter,Cooling:Electricity,timestep;').get
|
91
|
+
result << OpenStudio::IdfObject.load('Output:Meter,Heating:Electricity,timestep;').get
|
92
|
+
result << OpenStudio::IdfObject.load('Output:Meter,Heating:Gas,timestep;').get
|
93
|
+
result << OpenStudio::IdfObject.load('Output:Meter,InteriorLights:Electricity,timestep;').get
|
94
|
+
result << OpenStudio::IdfObject.load('Output:Meter,Fans:Electricity,timestep;').get
|
95
|
+
result << OpenStudio::IdfObject.load('Output:Meter,InteriorEquipment:Electricity,timestep;').get # Joules
|
96
|
+
result << OpenStudio::IdfObject.load('Output:Meter,ExteriorLighting:Electricity,timestep;').get # Joules
|
97
|
+
result << OpenStudio::IdfObject.load('Output:Meter,Electricity:Facility,timestep;').get # Joules
|
98
|
+
result << OpenStudio::IdfObject.load('Output:Meter,Electricity:Facility,timestep;').get ##Using this for data at timestep interval
|
99
|
+
result << OpenStudio::IdfObject.load('Output:Meter,Gas:Facility,timestep;').get # Joules
|
100
|
+
result << OpenStudio::IdfObject.load('Output:Meter,Heating:EnergyTransfer,timestep;').get # Joules
|
101
|
+
result << OpenStudio::IdfObject.load('Output:Meter,WaterSystems:EnergyTransfer,timestep;').get # Joules
|
102
|
+
# these variables are used for the modelica export.
|
103
|
+
result << OpenStudio::IdfObject.load('Output:Variable,*,Zone Predicted Sensible Load to Setpoint Heat Transfer Rate,timestep;').get # watts according to e+
|
104
|
+
result << OpenStudio::IdfObject.load('Output:Variable,*,Water Heater Total Demand Heat Transfer Rate,timestep;').get # Watts
|
105
|
+
|
106
|
+
return result
|
107
|
+
end
|
108
|
+
|
109
|
+
def extract_timeseries_into_matrix(sqlfile, data, variable_name, key_value = nil, default_if_empty = 0, timestep)
|
110
|
+
log "Executing query for #{variable_name}"
|
111
|
+
column_name = variable_name
|
112
|
+
if key_value
|
113
|
+
# ts = sqlfile.timeSeries('RUN PERIOD 1', 'Hourly', variable_name, key_value)
|
114
|
+
ts = sqlfile.timeSeries('RUN PERIOD 1', 'Zone Timestep', variable_name, key_value)
|
115
|
+
column_name += "_#{key_value}"
|
116
|
+
else
|
117
|
+
# ts = sqlfile.timeSeries('RUN PERIOD 1', 'Hourly', variable_name)
|
118
|
+
ts = sqlfile.timeSeries('RUN PERIOD 1', 'Zone Timestep', variable_name)
|
119
|
+
end
|
120
|
+
log 'Iterating over timeseries'
|
121
|
+
column = [column_name.delete(':').delete(' ')] # Set the header of the data to the variable name, removing : and spaces
|
122
|
+
|
123
|
+
if ts.empty?
|
124
|
+
log "No time series for #{variable_name}:#{key_value}... defaulting to #{default_if_empty}"
|
125
|
+
# needs to be data.size-1 since the column name is already stored above (+=)
|
126
|
+
column += [default_if_empty] * (data.size - 1)
|
127
|
+
else
|
128
|
+
ts = ts.get if ts.respond_to?(:get)
|
129
|
+
ts = ts.first if ts.respond_to?(:first)
|
130
|
+
|
131
|
+
start = Time.now
|
132
|
+
# Iterating in OpenStudio can take up to 60 seconds with 10min data. The quick_proc takes 0.03 seconds.
|
133
|
+
# for i in 0..ts.values.size - 1
|
134
|
+
# log "... at #{i}" if i % 10000 == 0
|
135
|
+
# column << ts.values[i]
|
136
|
+
# end
|
137
|
+
|
138
|
+
quick_proc = ts.values.to_s.split(',')
|
139
|
+
|
140
|
+
# the first and last have some cleanup items because of the Vector method
|
141
|
+
quick_proc[0] = quick_proc[0].gsub(/^.*\(/, '')
|
142
|
+
quick_proc[-1] = quick_proc[-1].delete(')')
|
143
|
+
column += quick_proc
|
144
|
+
|
145
|
+
log "Took #{Time.now - start} to iterate"
|
146
|
+
end
|
147
|
+
|
148
|
+
log 'Appending column to data'
|
149
|
+
|
150
|
+
# append the data to the end of the rows
|
151
|
+
if column.size == data.size
|
152
|
+
data.each_index do |index|
|
153
|
+
data[index] << column[index]
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
log "Finished extracting #{variable_name}"
|
158
|
+
end
|
159
|
+
|
160
|
+
def create_new_variable_sum(data, new_var_name, include_str, options = nil)
|
161
|
+
var_info = {
|
162
|
+
name: new_var_name,
|
163
|
+
var_indexes: []
|
164
|
+
}
|
165
|
+
data.each_with_index do |row, index|
|
166
|
+
if index.zero?
|
167
|
+
# Get the index of the columns to add
|
168
|
+
row.each do |c|
|
169
|
+
if c.include? include_str
|
170
|
+
var_info[:var_indexes] << row.index(c)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# add the new var to the header row
|
175
|
+
data[0] << var_info[:name]
|
176
|
+
else
|
177
|
+
# sum the values
|
178
|
+
sum = 0
|
179
|
+
var_info[:var_indexes].each do |var|
|
180
|
+
temp_v = row[var].to_f
|
181
|
+
if options.nil?
|
182
|
+
sum += temp_v
|
183
|
+
elsif options[:positive_only] && temp_v > 0
|
184
|
+
sum += temp_v
|
185
|
+
elsif options[:negative_only] && temp_v < 0
|
186
|
+
sum += temp_v
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
# Also round the data here, because we don't need 10 decimals
|
191
|
+
data[index] << sum.round(1)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def run(runner, user_arguments)
|
197
|
+
super(runner, user_arguments)
|
198
|
+
|
199
|
+
# get the last model and sql file
|
200
|
+
model = runner.lastOpenStudioModel
|
201
|
+
if model.empty?
|
202
|
+
runner.registerError('Cannot find last model.')
|
203
|
+
return false
|
204
|
+
end
|
205
|
+
model = model.get
|
206
|
+
|
207
|
+
# use the built-in error checking
|
208
|
+
return false unless runner.validateUserArguments(arguments(model), user_arguments)
|
209
|
+
|
210
|
+
# get the last model and sql file
|
211
|
+
model = runner.lastOpenStudioModel
|
212
|
+
if model.empty?
|
213
|
+
runner.registerError('Cannot find last model.')
|
214
|
+
return false
|
215
|
+
end
|
216
|
+
model = model.get
|
217
|
+
|
218
|
+
timesteps_per_hour=model.getTimestep.numberOfTimestepsPerHour.to_i
|
219
|
+
timestep=60/timesteps_per_hour #timestep in minutes
|
220
|
+
|
221
|
+
sqlFile = runner.lastEnergyPlusSqlFile
|
222
|
+
if sqlFile.empty?
|
223
|
+
runner.registerError('Cannot find last sql file.')
|
224
|
+
return false
|
225
|
+
end
|
226
|
+
sqlFile = sqlFile.get
|
227
|
+
model.setSqlFile(sqlFile)
|
228
|
+
|
229
|
+
# create a new csv with the values and save to the reports directory.
|
230
|
+
# assumptions:
|
231
|
+
# - all the variables exist
|
232
|
+
# - data are the same length
|
233
|
+
|
234
|
+
# initialize the rows with the header
|
235
|
+
log 'Starting to process Timeseries data'
|
236
|
+
# Initial header row
|
237
|
+
rows = [
|
238
|
+
['Date Time', 'Month', 'Day', 'Day of Week', 'Hour', 'Minute', 'SecondsFromStart']
|
239
|
+
]
|
240
|
+
|
241
|
+
# just grab one of the variables to get the date/time stamps
|
242
|
+
attribute_name = 'Electricity:Facility'
|
243
|
+
ts = sqlFile.timeSeries('RUN PERIOD 1', 'Zone Timestep', attribute_name)
|
244
|
+
if ts.empty?
|
245
|
+
runner.registerError("This feature does not have the attribute '#{attribute_name}' to enable this measure to work." \
|
246
|
+
"To resolve, simulate a building with electricity or remove this measure from your workflow.")
|
247
|
+
else
|
248
|
+
ts = ts.first
|
249
|
+
dt_base = nil
|
250
|
+
# Save off the date time values
|
251
|
+
ts.dateTimes.each_with_index do |dt, index|
|
252
|
+
dt_base = DateTime.parse(dt.to_s) if dt_base.nil?
|
253
|
+
dt_current = DateTime.parse(dt.to_s)
|
254
|
+
rows << [
|
255
|
+
DateTime.parse(dt.to_s).strftime('%m/%d/%Y %H:%M'),
|
256
|
+
dt.date.monthOfYear.value,
|
257
|
+
dt.date.dayOfMonth,
|
258
|
+
dt.date.dayOfWeek.value,
|
259
|
+
dt.time.hours,
|
260
|
+
dt.time.minutes,
|
261
|
+
dt_current.to_time.to_i - dt_base.to_time.to_i + timestep*60
|
262
|
+
]
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
# add in the other variables by columns -- should really pull this from the report variables defined above
|
267
|
+
extract_timeseries_into_matrix(sqlFile, rows, 'Site Outdoor Air Drybulb Temperature', 'Environment', 0, timestep)
|
268
|
+
extract_timeseries_into_matrix(sqlFile, rows, 'Site Outdoor Air Relative Humidity', 'Environment', 0, timestep)
|
269
|
+
extract_timeseries_into_matrix(sqlFile, rows, 'Heating:Electricity', nil, 0, timestep)
|
270
|
+
extract_timeseries_into_matrix(sqlFile, rows, 'Heating:Gas', nil, 0, timestep)
|
271
|
+
extract_timeseries_into_matrix(sqlFile, rows, 'Cooling:Electricity', nil, 0, timestep)
|
272
|
+
extract_timeseries_into_matrix(sqlFile, rows, 'Electricity:Facility', nil, 0, timestep)
|
273
|
+
extract_timeseries_into_matrix(sqlFile, rows, 'Gas:Facility', nil, 0, timestep)
|
274
|
+
extract_timeseries_into_matrix(sqlFile, rows, 'Heating:EnergyTransfer', nil, 0, timestep)
|
275
|
+
extract_timeseries_into_matrix(sqlFile, rows, 'WaterSystems:EnergyTransfer', nil, 0, timestep)
|
276
|
+
|
277
|
+
# get all zones and save the names for later use in aggregation.
|
278
|
+
tz_names = []
|
279
|
+
model.getThermalZones.each do |tz|
|
280
|
+
tz_names << tz.name.get if tz.name.is_initialized
|
281
|
+
extract_timeseries_into_matrix(sqlFile, rows, 'Zone Predicted Sensible Load to Setpoint Heat Transfer Rate', tz_names.last, 0, timestep)
|
282
|
+
extract_timeseries_into_matrix(sqlFile, rows, 'Water Heater Heating Rate', tz_names.last, 0, timestep)
|
283
|
+
end
|
284
|
+
|
285
|
+
# sum up a couple of the columns and create a new columns
|
286
|
+
create_new_variable_sum(rows, 'TotalSensibleLoad', 'ZonePredictedSensibleLoadtoSetpointHeatTransferRate')
|
287
|
+
create_new_variable_sum(rows, 'TotalCoolingSensibleLoad', 'ZonePredictedSensibleLoadtoSetpointHeatTransferRate', negative_only: true)
|
288
|
+
create_new_variable_sum(rows, 'TotalHeatingSensibleLoad', 'ZonePredictedSensibleLoadtoSetpointHeatTransferRate', positive_only: true)
|
289
|
+
create_new_variable_sum(rows, 'TotalWaterHeating', 'WaterHeaterHeatingRate')
|
290
|
+
|
291
|
+
# convert this to CSV object
|
292
|
+
File.open('./building_loads.csv', 'w') do |f|
|
293
|
+
rows.each do |row|
|
294
|
+
f << row.join(',') << "\n"
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
# covert the row data into the format needed by modelica
|
299
|
+
modelica_data = [['seconds', 'cooling', 'heating', 'waterheating']]
|
300
|
+
seconds_index = nil
|
301
|
+
total_water_heating_index = nil
|
302
|
+
total_cooling_sensible_index = nil
|
303
|
+
total_heating_sensible_index = nil
|
304
|
+
peak_cooling = 0
|
305
|
+
peak_heating = 0
|
306
|
+
peak_water_heating = 0
|
307
|
+
rows.each_with_index do |row, index|
|
308
|
+
if index.zero?
|
309
|
+
seconds_index = row.index('SecondsFromStart')
|
310
|
+
total_cooling_sensible_index = row.index('TotalCoolingSensibleLoad')
|
311
|
+
total_heating_sensible_index = row.index('TotalHeatingSensibleLoad')
|
312
|
+
total_water_heating_index = row.index('TotalWaterHeating')
|
313
|
+
else
|
314
|
+
new_data = [
|
315
|
+
row[seconds_index],
|
316
|
+
row[total_cooling_sensible_index],
|
317
|
+
row[total_heating_sensible_index],
|
318
|
+
row[total_water_heating_index]
|
319
|
+
]
|
320
|
+
|
321
|
+
modelica_data << new_data
|
322
|
+
|
323
|
+
# store the peaks
|
324
|
+
peak_cooling = row[total_cooling_sensible_index] if row[total_cooling_sensible_index] < peak_cooling
|
325
|
+
peak_heating = row[total_heating_sensible_index] if row[total_heating_sensible_index] > peak_heating
|
326
|
+
peak_water_heating = row[total_water_heating_index] if row[total_water_heating_index] > peak_water_heating
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
File.open('./modelica.mos', 'w') do |f|
|
331
|
+
f << "#1\n"
|
332
|
+
f << "#Heating and Cooling Model loads from OpenStudio Prototype Buildings\n"
|
333
|
+
f << "# Building Type: {{BUILDINGTYPE}}\n"
|
334
|
+
f << "# Climate Zone: {{CLIMATEZONE}}\n"
|
335
|
+
f << "# Vintage: {{VINTAGE}}\n"
|
336
|
+
f << "# Simulation ID (for debugging): {{SIMID}}\n"
|
337
|
+
f << "# URL: https://github.com/urbanopt/openstudio-prototype-loads\n"
|
338
|
+
f << "\n"
|
339
|
+
f << "#First column: Seconds in the year (loads are hourly)\n"
|
340
|
+
f << "#Second column: cooling loads in Watts (as negative numbers).\n"
|
341
|
+
f << "#Third column: space heating loads in Watts\n"
|
342
|
+
f << "#Fourth column: water heating in Watts\n"
|
343
|
+
f << "\n"
|
344
|
+
f << "#Peak space cooling load = #{peak_cooling} Watts\n"
|
345
|
+
f << "#Peak space heating load = #{peak_heating} Watts\n"
|
346
|
+
f << "#Peak water heating load = #{peak_water_heating} Watts\n"
|
347
|
+
f << "double tab1(8760,4)\n"
|
348
|
+
modelica_data.each_with_index do |row, index|
|
349
|
+
next if index.zero?
|
350
|
+
f << row.join(';') << "\n"
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
# Find the total runtime for energyplus and save it into a registerValue
|
355
|
+
total_time = -999
|
356
|
+
location_of_file = ['../eplusout.end', './run/eplusout.end']
|
357
|
+
first_index = location_of_file.map { |f| File.exist?(f) }.index(true)
|
358
|
+
if first_index
|
359
|
+
match = File.read(location_of_file[first_index]).to_s.match(/Elapsed.Time=(.*)hr(.*)min(.*)sec/)
|
360
|
+
total_time = match[1].to_i * 3600 + match[2].to_i * 60 + match[3].to_f
|
361
|
+
end
|
362
|
+
|
363
|
+
runner.registerValue('energyplus_runtime', total_time, 'sec')
|
364
|
+
runner.registerValue('peak_cooling_load', peak_cooling, 'W')
|
365
|
+
runner.registerValue('peak_heating_load', peak_heating, 'W')
|
366
|
+
runner.registerValue('peak_water_heating', peak_water_heating, 'W')
|
367
|
+
|
368
|
+
return true
|
369
|
+
ensure
|
370
|
+
sqlFile.close if sqlFile
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
# register the measure to be used by the application
|
375
|
+
ExportModelicaLoads.new.registerWithApplication
|