urbanopt-reporting 0.3.0 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|