openstudio-standards 0.8.5 → 0.8.7
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/data/standards/test_performance_expected_dd_results.csv +90 -90
- data/lib/openstudio-standards/btap/activity.rb +858 -61
- data/lib/openstudio-standards/btap/attributes.rb +297 -103
- data/lib/openstudio-standards/btap/bridging.rb +1335 -593
- data/lib/openstudio-standards/btap/btap.rb +60 -181
- data/lib/openstudio-standards/btap/carbon/btap_carbon.rb +199 -142
- data/lib/openstudio-standards/btap/common/constructions.json +1275 -0
- data/lib/openstudio-standards/btap/common/costs.csv +1969 -0
- data/lib/openstudio-standards/btap/common/costs_local_factors.csv +2315 -0
- data/lib/openstudio-standards/btap/common/materials_glazing.csv +61 -0
- data/lib/openstudio-standards/btap/{common_resources → common}/materials_hvac.csv +1685 -1685
- data/lib/openstudio-standards/btap/{common_resources → common}/materials_lighting.csv +266 -266
- data/lib/openstudio-standards/btap/common/materials_opaque.csv +214 -0
- data/lib/openstudio-standards/btap/common/necb_building_types.csv +35 -0
- data/lib/openstudio-standards/btap/common/necb_space_types.csv +110 -0
- data/lib/openstudio-standards/btap/common/thermal_bridging.csv +73 -0
- data/lib/openstudio-standards/btap/costing/btap_costing.rb +346 -429
- data/lib/openstudio-standards/btap/costing/database.rb +104 -0
- data/lib/openstudio-standards/btap/costing/daylighting_sensor_control_costing.rb +356 -344
- data/lib/openstudio-standards/btap/costing/dcv_costing.rb +282 -296
- data/lib/openstudio-standards/btap/costing/envelope_costing.rb +179 -192
- data/lib/openstudio-standards/btap/costing/heating_cooling_costing.rb +2477 -2316
- data/lib/openstudio-standards/btap/costing/led_lighting_costing.rb +127 -142
- data/lib/openstudio-standards/btap/costing/lighting_costing.rb +216 -198
- data/lib/openstudio-standards/btap/costing/nv_costing.rb +522 -523
- data/lib/openstudio-standards/btap/costing/pv_ground_costing.rb +649 -649
- data/lib/openstudio-standards/btap/costing/shw_costing.rb +626 -625
- data/lib/openstudio-standards/btap/costing/thermal_bridging_costing.rb +72 -0
- data/lib/openstudio-standards/btap/costing/ventilation_costing.rb +2363 -2361
- data/lib/openstudio-standards/btap/deprecated.rb +1033 -0
- data/lib/openstudio-standards/btap/envelope.rb +313 -572
- data/lib/openstudio-standards/btap/fileio.rb +152 -1070
- data/lib/openstudio-standards/btap/geometry.rb +486 -766
- data/lib/openstudio-standards/btap/linear_regression.rb +130 -0
- data/lib/openstudio-standards/btap/paths.rb +46 -0
- data/lib/openstudio-standards/btap/qaqc/analysis.rb +163 -0
- data/lib/openstudio-standards/btap/qaqc/data.rb +2293 -0
- data/lib/openstudio-standards/btap/qaqc/datapoint.rb +641 -0
- data/lib/openstudio-standards/btap/schedules.rb +11 -611
- data/lib/openstudio-standards/btap/structure.rb +574 -189
- data/lib/openstudio-standards/constructions/materials/information.rb +1 -1
- data/lib/openstudio-standards/create_typical/create_typical.rb +1 -1
- data/lib/openstudio-standards/exterior_lighting/create.rb +135 -85
- data/lib/openstudio-standards/exterior_lighting/data/typical_exterior_lighting.json +20 -0
- data/lib/openstudio-standards/exterior_lighting/information.rb +23 -2
- data/lib/openstudio-standards/geometry/create.rb +7 -3
- data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.Model.rb +3 -2
- data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Model.rb +3 -2
- data/lib/openstudio-standards/prototypes/common/data/thermostat_schedule_lookup.json +84 -84
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.hvac_systems.rb +4 -4
- data/lib/openstudio-standards/refrigeration/create_walkin.rb +45 -5
- data/lib/openstudio-standards/refrigeration/data/refrigerated_walkins.csv +75 -75
- data/lib/openstudio-standards/schedules/parametric.rb +6 -0
- data/lib/openstudio-standards/service_water_heating/create_typical.rb +10 -3
- data/lib/openstudio-standards/service_water_heating/create_water_heating_loop.rb +30 -14
- data/lib/openstudio-standards/service_water_heating/information.rb +4 -1
- data/lib/openstudio-standards/sql_file/unmet_hours.rb +2 -1
- data/lib/openstudio-standards/standards/Standards.CoilCoolingDXSingleSpeed.rb +3 -1
- data/lib/openstudio-standards/standards/Standards.CoilHeatingDXSingleSpeed.rb +3 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.boilers.json +12 -0
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.construction_properties.json +18432 -3072
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.boilers.json +26 -0
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.construction_properties.json +8532 -1422
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.boilers.json +26 -0
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.construction_properties.json +8532 -1422
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.boilers.json +16 -0
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.computer_room_acs.json +30 -30
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.construction_properties.json +7560 -1260
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.PumpVariableSpeed.rb +1 -2
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/data/ashrae_90_1_2016.boilers.json +16 -0
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/data/ashrae_90_1_2016.construction_properties.json +7560 -1260
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb +3 -3
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.PumpVariableSpeed.rb +1 -2
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/data/ashrae_90_1_2019.boilers.json +22 -0
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/data/ashrae_90_1_2019.construction_properties.json +7236 -1206
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/data/ashrae_90_1_2019.furnaces.json +223 -19
- data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.schedules.json +37 -1
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.boilers.json +3 -0
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.construction_properties.json +6900 -1150
- data/lib/openstudio-standards/standards/cbes/data/cbes.schedules.json +1 -1
- data/lib/openstudio-standards/standards/deer/data/deer.schedules.json +1 -1
- data/lib/openstudio-standards/standards/necb/BTAP1980TO2010/data/surface_thermal_transmittance.json +76 -40
- data/lib/openstudio-standards/standards/necb/BTAPPRE1980/data/surface_thermal_transmittance.json +76 -40
- data/lib/openstudio-standards/standards/necb/ECMS/hvac_systems.rb +6 -4
- data/lib/openstudio-standards/standards/necb/NECB2011/NECB2011_QAQC.json +2988 -0
- data/lib/openstudio-standards/standards/necb/NECB2011/autozone.rb +25 -3
- data/lib/openstudio-standards/standards/necb/NECB2011/building_envelope.rb +672 -534
- data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/Hospital.osm +1791 -1792
- data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/LEEPMultiTower.osm +7 -1
- data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/LEEPTownHouse.osm +7 -1
- data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/LargeHotel.osm +5 -6
- data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/LargeOffice.osm +8 -9
- data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/NorthernEducation.osm +10 -4
- data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/NorthernHealthCare.osm +14 -15
- data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/Outpatient.osm +7 -1
- data/lib/openstudio-standards/standards/necb/NECB2011/data/surface_thermal_transmittance.json +76 -40
- data/lib/openstudio-standards/standards/necb/NECB2011/hvac_systems.rb +14 -6
- data/lib/openstudio-standards/standards/necb/NECB2011/necb_2011.rb +542 -130
- data/lib/openstudio-standards/standards/necb/NECB2011/qaqc/necb_qaqc.rb +30 -63
- data/lib/openstudio-standards/standards/necb/NECB2011/service_water_heating.rb +7 -2
- data/lib/openstudio-standards/standards/necb/NECB2015/data/surface_thermal_transmittance.json +90 -0
- data/lib/openstudio-standards/standards/necb/NECB2015/necb_2015.rb +8 -6
- data/lib/openstudio-standards/standards/necb/NECB2017/data/surface_thermal_transmittance.json +76 -40
- data/lib/openstudio-standards/standards/necb/NECB2017/necb_2017.rb +2 -1
- data/lib/openstudio-standards/standards/necb/NECB2020/building_envelope.rb +0 -117
- data/lib/openstudio-standards/standards/necb/NECB2020/data/surface_thermal_transmittance.json +76 -45
- data/lib/openstudio-standards/standards/necb/NECB2020/necb_2020.rb +218 -0
- data/lib/openstudio-standards/standards/necb/common/construction_defaults.osm +12 -7
- data/lib/openstudio-standards/standards/standard.rb +1 -1
- data/lib/openstudio-standards/version.rb +1 -1
- data/lib/openstudio-standards.rb +9 -4
- metadata +59 -66
- data/data/inventory/thermal_bridging.csv +0 -90
- data/data/standards/OpenStudio_Standards-ashrae_90_1-ALL-comstock(space_types).xlsx +0 -0
- data/data/standards/openstudio_standards_duplicates_log.csv +0 -7962
- data/lib/openstudio-standards/btap/NECB_building_types.csv +0 -35
- data/lib/openstudio-standards/btap/NECB_space_types.csv +0 -109
- data/lib/openstudio-standards/btap/WeatherData1.json +0 -2110
- data/lib/openstudio-standards/btap/WeatherData1.xlsx +0 -0
- data/lib/openstudio-standards/btap/btap_result.rb +0 -1144
- data/lib/openstudio-standards/btap/btap_test_helper.rb +0 -86
- data/lib/openstudio-standards/btap/common_paths.rb +0 -81
- data/lib/openstudio-standards/btap/common_resources/ConstructionProperties.csv +0 -52
- data/lib/openstudio-standards/btap/common_resources/Constructions.csv +0 -37
- data/lib/openstudio-standards/btap/common_resources/construction_sets.csv +0 -1270
- data/lib/openstudio-standards/btap/common_resources/constructions_glazing.csv +0 -121
- data/lib/openstudio-standards/btap/common_resources/constructions_opaque.csv +0 -2256
- data/lib/openstudio-standards/btap/common_resources/costs.csv +0 -1897
- data/lib/openstudio-standards/btap/common_resources/costs_local_factors.csv +0 -2315
- data/lib/openstudio-standards/btap/common_resources/materials_glazing.csv +0 -35
- data/lib/openstudio-standards/btap/common_resources/materials_opaque.csv +0 -164
- data/lib/openstudio-standards/btap/costing/btap_measure_helper.rb +0 -359
- data/lib/openstudio-standards/btap/costing/btap_workflow.rb +0 -117
- data/lib/openstudio-standards/btap/costing/copy_test_results_files_to_expected_results.rb +0 -11
- data/lib/openstudio-standards/btap/costing/cost_building_from_file.rb +0 -136
- data/lib/openstudio-standards/btap/costing/costing_database_wrapper.rb +0 -173
- data/lib/openstudio-standards/btap/costing/dummy.epw +0 -8768
- data/lib/openstudio-standards/btap/costing/dummy.osm +0 -5320
- data/lib/openstudio-standards/btap/costing/neb_end_use_prices.csv +0 -42
- data/lib/openstudio-standards/btap/costing/necb_2011_spacetype_info.csv +0 -225
- data/lib/openstudio-standards/btap/costing/necb_reference_runs.csv +0 -28705
- data/lib/openstudio-standards/btap/costing/parallel_tests.rb +0 -92
- data/lib/openstudio-standards/btap/costing/test_list.txt +0 -15
- data/lib/openstudio-standards/btap/costing/test_run_all_test_locally.rb +0 -27
- data/lib/openstudio-standards/btap/costing/test_run_costing_tests.rb +0 -80
- data/lib/openstudio-standards/btap/necb_2011_spacetype_info.csv +0 -225
- data/lib/openstudio-standards/btap/utilities/Add_template_field_to_json.rb +0 -22
- data/lib/openstudio-standards/btap/utilities/convert_surfaces_to_adiabatic_necb_8426.rb +0 -204
- data/lib/openstudio-standards/btap/utilities/generate_space_types.rb +0 -8
- data/lib/openstudio-standards/btap/utilities/necb_to_epw_map.rb +0 -50
- data/lib/openstudio-standards/btap/utilities/os_sim_extract.rb +0 -48
- data/lib/openstudio-standards/btap/utilities/rename_surfaces.rb +0 -24
- data/lib/openstudio-standards/btap/utilities/round_surf_coords.rb +0 -32
- data/lib/openstudio-standards/btap/utilities/sched_create.rb +0 -145
- data/lib/openstudio-standards/btap/utilities/set_mult_to_adiabatic.rb +0 -53
- data/lib/openstudio-standards/btap/utilities/space_type.rb +0 -78
- data/lib/openstudio-standards/btap/utilities/weatherData1_xlsx_to_json.rb +0 -56
- data/lib/openstudio-standards/btap/vintagizer.rb +0 -161
- data/lib/openstudio-standards/btap/visualization.rb +0 -72
- data/lib/openstudio-standards/standards/necb/NECB2011/data/necb_2011_spacetype_info.csv +0 -225
- data/lib/openstudio-standards/standards/necb/common/btap_analysis.rb +0 -79
- data/lib/openstudio-standards/standards/necb/common/btap_data.rb +0 -2656
- data/lib/openstudio-standards/standards/necb/common/btap_datapoint.rb +0 -653
- data/lib/openstudio-standards/standards/necb/common/necb_reference_runs.csv +0 -28705
- data/lib/openstudio-standards/standards/necb/common/utility_pricing_2025-02-20.csv +0 -92
- /data/lib/openstudio-standards/btap/{common_resources → common}/carbon_frame.csv +0 -0
- /data/lib/openstudio-standards/btap/{common_resources → common}/carbon_glazing.csv +0 -0
- /data/lib/openstudio-standards/btap/{common_resources → common}/carbon_opaque.csv +0 -0
- /data/lib/openstudio-standards/btap/{common_resources → common}/hvac_vent_ahu.csv +0 -0
- /data/lib/openstudio-standards/btap/{common_resources → common}/lighting.csv +0 -0
- /data/lib/openstudio-standards/btap/{common_resources → common}/lighting_sets.csv +0 -0
- /data/lib/openstudio-standards/btap/{common_resources → common}/locations.csv +0 -0
- /data/lib/openstudio-standards/btap/{costing → common}/mech_sizing.json +0 -0
|
@@ -1,215 +1,202 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
gsub(/([a-z\d])([A-Z])/, '\1_\2').
|
|
6
|
-
tr("-", "_").
|
|
7
|
-
downcase
|
|
8
|
-
end
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
class BTAPCosting
|
|
12
|
-
def cost_audit_envelope(model, prototype_creator)
|
|
13
|
-
@attributes.surface_types.each do |surface_type|
|
|
14
|
-
@costing_report["envelope"]["#{surface_type.underscore}_cost"] = 0.00
|
|
15
|
-
@costing_report["envelope"]["#{surface_type.underscore}_area_m2"] = 0.0
|
|
16
|
-
@costing_report["envelope"]["#{surface_type.underscore}_cost_per_m2"] = 0.00
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
@costing_report["envelope"]["construction_costs"] = []
|
|
1
|
+
module BTAP
|
|
2
|
+
class Costing
|
|
3
|
+
# @param prototype_creator [Standard]
|
|
4
|
+
def cost_audit_envelope(prototype_creator)
|
|
20
5
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
6
|
+
# Populate the `costing_report` hash to report costing details per surface
|
|
7
|
+
# type.
|
|
8
|
+
@attributes.surface_types.each do |surface_type|
|
|
9
|
+
@costing_report["envelope"]["#{@attributes.surface_types_to_snake[surface_type]}_cost"] = 0.0
|
|
10
|
+
@costing_report["envelope"]["#{@attributes.surface_types_to_snake[surface_type]}_area_m2"] = 0.0
|
|
11
|
+
@costing_report["envelope"]["#{@attributes.surface_types_to_snake[surface_type]}_cost_per_m2"] = 0.0
|
|
12
|
+
end
|
|
24
13
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
raise ("standards Space type and building type is not defined for space:#{space.name.get}. Skipping this space for costing.")
|
|
14
|
+
# Cost all the constructions found by BTAP Attributes.
|
|
15
|
+
@attributes.constructions.each_value do |construction|
|
|
16
|
+
cost_construction(construction, @costing_report['province_state'], @costing_report['city'])
|
|
29
17
|
end
|
|
30
18
|
|
|
19
|
+
@costing_report["envelope"]["surface_type_costs"] = []
|
|
20
|
+
@costing_report["envelope"]["construction_costs"] = {}
|
|
21
|
+
|
|
22
|
+
total_envelope_cost = 0
|
|
31
23
|
@attributes.surface_types.each do |surface_type|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
construction[
|
|
41
|
-
construction[
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
24
|
+
unless @attributes.surface_types_to_assembly_tallies[surface_type].empty?
|
|
25
|
+
@attributes.surface_types_to_assembly_tallies[surface_type].each_pair do |assembly_name, tallies|
|
|
26
|
+
|
|
27
|
+
# Tallies collect surface areas for all surfaces in a type that
|
|
28
|
+
# contain the same assembly. More than one assembly can be present
|
|
29
|
+
# in the case of custom building types.
|
|
30
|
+
total_area = tallies["area"]
|
|
31
|
+
construction = @attributes.constructions[assembly_name]
|
|
32
|
+
rsi = construction["rsi"]
|
|
33
|
+
surface_is_glazing = construction["type"] == "glazing"
|
|
34
|
+
|
|
35
|
+
# Use the cost_range_array to interpolate the estimated cost for the
|
|
36
|
+
# RSI of the current surface.
|
|
37
|
+
cost_range_array = construction["subsets"].map { |subset| [subset["rsi"], subset["cost"]] }
|
|
38
|
+
cost, notes = BTAP::LinearRegression.interpolate(x_y_array: cost_range_array, x2: rsi)
|
|
39
|
+
|
|
40
|
+
# Calculate SHGC/film cost.
|
|
41
|
+
film_cost = 0.0
|
|
42
|
+
if construction["type"] == "glazing"
|
|
43
|
+
|
|
44
|
+
# Get the closest value in materials_glazing sheet of SolarFilms.
|
|
45
|
+
material_row = @costing_database["raw"]["materials_glazing"].select { |row|
|
|
46
|
+
row['material_type'] == 'Solarfilms' }.min_by {|row|
|
|
47
|
+
(construction["shgc"].to_f - row['solar_heat_gain_coefficient'].to_f).abs}
|
|
48
|
+
|
|
49
|
+
standard_film_cost = getCost(material_row['description'], material_row, 1.0)
|
|
50
|
+
regional_factors = get_regional_cost_factors(
|
|
51
|
+
@costing_report['province_state'],
|
|
52
|
+
@costing_report['city'],
|
|
53
|
+
material_row)
|
|
54
|
+
|
|
55
|
+
# Multiply regional cost and sum costs. Zip adds the arrays
|
|
56
|
+
# together, map multiplies each row and divides by 100.0 since the
|
|
57
|
+
# regional factor is a percentage.
|
|
58
|
+
film_cost = standard_film_cost.zip(regional_factors).map { |cost,region_factor|
|
|
59
|
+
cost * region_factor / 100.0 }.inject(0, :+)
|
|
60
|
+
end
|
|
45
61
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
total_area_feet = (OpenStudio.convert(total_area, "m^2", "ft^2").get).to_f
|
|
63
|
+
total_cost = (cost + film_cost) * total_area_feet
|
|
64
|
+
total_envelope_cost += total_cost
|
|
65
|
+
|
|
66
|
+
# Bin the cost to tally it up per-construction later.
|
|
67
|
+
tallies["cost"] = total_cost
|
|
68
|
+
|
|
69
|
+
# Bin the costing by construction type and rsi.
|
|
70
|
+
@costing_report["envelope"]["surface_type_costs"] << {
|
|
71
|
+
"assembly_name" => assembly_name,
|
|
72
|
+
"surface_type" => surface_type,
|
|
73
|
+
"conductance" => rsi.round(3),
|
|
74
|
+
"area" => total_area.round(2),
|
|
75
|
+
"cost" => total_cost.round(2),
|
|
76
|
+
"cost_per_area" => (total_cost / total_area).round(2),
|
|
77
|
+
"notes" => notes
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
@costing_report["envelope"]["#{@attributes.surface_types_to_snake[surface_type]}_cost"] += total_cost
|
|
81
|
+
@costing_report["envelope"]["#{@attributes.surface_types_to_snake[surface_type]}_area_m2"] += total_area
|
|
82
|
+
end
|
|
83
|
+
@costing_report["envelope"]["#{@attributes.surface_types_to_snake[surface_type]}_cost_per_m2"] = (
|
|
84
|
+
@costing_report["envelope"]["#{@attributes.surface_types_to_snake[surface_type]}_cost"] /
|
|
85
|
+
@costing_report["envelope"]["#{@attributes.surface_types_to_snake[surface_type]}_area_m2"])
|
|
86
|
+
|
|
87
|
+
if @costing_report["envelope"]["#{@attributes.surface_types_to_snake[surface_type]}_cost_per_m2"].nan?
|
|
88
|
+
@costing_report["envelope"]["#{@attributes.surface_types_to_snake[surface_type]}_cost_per_m2"] = 0.0
|
|
89
|
+
end
|
|
65
90
|
end
|
|
66
|
-
|
|
67
|
-
cost_range_array.sort! { |a, b| a[0] <=> b[0] }
|
|
91
|
+
end
|
|
68
92
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
93
|
+
# Bin costs by entire constructions.
|
|
94
|
+
@attributes.surface_types_to_assembly_tallies.values.filter {|tallies| not tallies.empty?}.each do |entry|
|
|
95
|
+
entry.each_pair do |assembly_name, tallies|
|
|
96
|
+
if @costing_report["envelope"]["construction_costs"].has_key?(assembly_name)
|
|
97
|
+
bin = @costing_report["envelope"]["construction_costs"][assembly_name]
|
|
98
|
+
bin["area"] = (bin["area"] + tallies["area"]).round(2)
|
|
99
|
+
bin["cost"] = (bin["cost"] + tallies["cost"]).round(2)
|
|
100
|
+
bin["cost_per_area"] = (bin["cost"] / bin["area"]).round(2)
|
|
101
|
+
else
|
|
102
|
+
@costing_report["envelope"]["construction_costs"][assembly_name] = {
|
|
103
|
+
"conductance" => @attributes.constructions[assembly_name]["rsi"].round(3),
|
|
104
|
+
"area" => tallies["area"].round(2),
|
|
105
|
+
"cost" => tallies["cost"].round(2),
|
|
106
|
+
"cost_per_area" => (tallies["cost"] / tallies["area"]).round(2)
|
|
107
|
+
}
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
73
111
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
112
|
+
# Parapets aren't explicitly modeled in an OpenStudio model. If TBD was run,
|
|
113
|
+
# account for parapets by taking the calculated parapet length and multiply
|
|
114
|
+
# it by 1m to factor it into the total cost. So, take the cost of the
|
|
115
|
+
# exterior walls per m^2 and multiply it buy the total parapet length.
|
|
116
|
+
if @attributes.tbd_enabled
|
|
117
|
+
wall_cost_per_m2 = @costing_report["envelope"]["exterior_wall_cost_per_m2"]
|
|
118
|
+
parapet_cost = @attributes.tbd_edge_tallies["parapet"].values.first * wall_cost_per_m2
|
|
119
|
+
@costing_report["envelope"]["parapet_cost"] = parapet_cost.round(2)
|
|
120
|
+
total_envelope_cost += parapet_cost
|
|
121
|
+
end
|
|
78
122
|
|
|
123
|
+
# When using thermal bridging it may create too demanding of a model, or
|
|
124
|
+
# when data is insufficient, some R-factors will be outside of the data
|
|
125
|
+
# and BTAP::LinearRegression will refuse to extrapolate beyond its default
|
|
126
|
+
# range. If that occured, don't raise an error but add a really high
|
|
127
|
+
# number to the envelope cost to make the user aware of what happened.
|
|
128
|
+
if BTAP::LinearRegression.extrapolation_boundaries_exceeded?
|
|
129
|
+
revolutionary_engineering_technology_fudge_factor = 1000000000000
|
|
130
|
+
total_envelope_cost += revolutionary_engineering_technology_fudge_factor
|
|
131
|
+
@costing_report["envelope"]["unrealistic_assembly_cost"] = revolutionary_engineering_technology_fudge_factor
|
|
132
|
+
@costing_report["envelope"]["unrealistic_assembly_note"] = \
|
|
133
|
+
"Could not extrapolate beyond the given range. The given model might be unrealistic to build because no " \
|
|
134
|
+
"assemblies exist in the database with the given heat transfer requirements. This could be that the " \
|
|
135
|
+
"thermal bridging module created too demanding of a model given the performance constraints. Try changing " \
|
|
136
|
+
"the `tbd_option` parameter in your run options."
|
|
137
|
+
end
|
|
79
138
|
|
|
80
|
-
|
|
139
|
+
# The following attribute establishes for sure whether the TBD module
|
|
140
|
+
# was able to produce all compliant assemblies when uprating.
|
|
141
|
+
unless @attributes.tbd_compliance.nil?
|
|
142
|
+
@costing_report["envelope"]["tbd_compliance"] = @attributes.tbd_compliance
|
|
143
|
+
end
|
|
81
144
|
|
|
145
|
+
# Round everything at the end.
|
|
146
|
+
@attributes.surface_types.each do |surface_type|
|
|
147
|
+
@costing_report["envelope"]["#{@attributes.surface_types_to_snake[surface_type]}_cost"] = \
|
|
148
|
+
@costing_report["envelope"]["#{@attributes.surface_types_to_snake[surface_type]}_cost"].round(2)
|
|
149
|
+
@costing_report["envelope"]["#{@attributes.surface_types_to_snake[surface_type]}_area_m2"] = \
|
|
150
|
+
@costing_report["envelope"]["#{@attributes.surface_types_to_snake[surface_type]}_area_m2"].round(2)
|
|
151
|
+
@costing_report["envelope"]["#{@attributes.surface_types_to_snake[surface_type]}_cost_per_m2"] = \
|
|
152
|
+
@costing_report["envelope"]["#{@attributes.surface_types_to_snake[surface_type]}_cost_per_m2"].round(2)
|
|
153
|
+
end
|
|
82
154
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
exterpolate_percentage_range = 30.0
|
|
86
|
-
cost = interpolate(x_y_array: cost_range_array, x2: rsi, exterpolate_percentage_range: exterpolate_percentage_range)
|
|
155
|
+
@costing_report["envelope"]["total_envelope_cost"] = total_envelope_cost.to_f.round(2)
|
|
156
|
+
puts "\nEnvelope costing data successfully generated. Total envelope cost is $#{total_envelope_cost.to_f.round(2)}"
|
|
87
157
|
|
|
158
|
+
return total_envelope_cost
|
|
159
|
+
end
|
|
88
160
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
161
|
+
# Append the "cost" key-value pair to a construction hash by calculating
|
|
162
|
+
# the cost from each layer from either the opaque (materials_opaque.csv)
|
|
163
|
+
# or glazing (materials_glazing.csv) while also accounting for regional and
|
|
164
|
+
# installation factors.
|
|
165
|
+
#
|
|
166
|
+
# @param construction [Hash]
|
|
167
|
+
# @param province_state [String]
|
|
168
|
+
# @param city [String]
|
|
169
|
+
def cost_construction(construction, province_state, city)
|
|
170
|
+
material_id = "materials_#{construction["type"]}_id"
|
|
171
|
+
materials_database = @costing_database["raw"]["materials_#{construction["type"]}"]
|
|
172
|
+
total_with_op = 0.0
|
|
173
|
+
|
|
174
|
+
construction["subsets"].each do |subset|
|
|
175
|
+
total_with_op = 0
|
|
176
|
+
subset["id_layers"].each do |material_index|
|
|
177
|
+
material = materials_database.find { |data| data[material_id] == material_index }
|
|
178
|
+
if material.nil?
|
|
179
|
+
raise("Material ID #{material_index} was not found in the materials_#{construction["type"]} database.")
|
|
100
180
|
else
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
notes = "RSI out of the range (#{'%.2f' % rsi}). Range for #{space.construction_set[surface_type]} is #{'%.2f' % cost_range_array.first[0]}-#{'%.2f' % cost_range_array.last[0]}.Using extrapolation up to +/-30% of library boundaries. "
|
|
181
|
+
costing_data = @costing_database['costs'].detect { |data| data['id'] == material['id'] }
|
|
182
|
+
if costing_data.nil?
|
|
183
|
+
raise("Material ID #{material_index} was not found in the costing database")
|
|
105
184
|
else
|
|
106
|
-
|
|
185
|
+
regional_material, regional_installation = get_regional_cost_factors(province_state, city, material)
|
|
186
|
+
|
|
187
|
+
# Get cost information from lookup.
|
|
188
|
+
material_cost = costing_data['baseCosts']['materialOpCost'] * material['material_mult'].to_f
|
|
189
|
+
labour_cost = costing_data['baseCosts']['laborOpCost'] * material['labour_mult'].to_f
|
|
190
|
+
equipment_cost = costing_data['baseCosts']['equipmentOpCost']
|
|
191
|
+
layer_cost = (((material_cost * regional_material / 100.0) + \
|
|
192
|
+
(labour_cost * regional_installation / 100.0) + equipment_cost) * \
|
|
193
|
+
material['quantity'].to_f).round(2)
|
|
194
|
+
total_with_op += layer_cost
|
|
107
195
|
end
|
|
108
196
|
end
|
|
109
|
-
|
|
110
|
-
# Calculate SHGC/film cost
|
|
111
|
-
film_cost = 0.0
|
|
112
|
-
if surfaceIsGlazing
|
|
113
|
-
#Get SHGC from surface.
|
|
114
|
-
shgc = OpenstudioStandards::Constructions.construction_get_solar_transmittance(surface.construction.get.to_Construction.get)
|
|
115
|
-
# Get the closest value in materials_glazing sheet of SolarFilms.
|
|
116
|
-
material_row = @costing_database["raw"]["materials_glazing"].select{ |row| row['material_type'] == 'Solarfilms' }.min_by {|row| (shgc.to_f - row['solar_heat_gain_coefficient'].to_f).abs}
|
|
117
|
-
standard_film_cost = getCost(material_row['description'], material_row, 1.0)
|
|
118
|
-
regional_factors = get_regional_cost_factors(@costing_report['province_state'], @costing_report['city'], material_row)
|
|
119
|
-
# mult regional cost and sum costs. Zip adds the arrays together, map multiplies each row and divides by 100.0 since the regional factor is in percents.
|
|
120
|
-
film_cost = standard_film_cost.zip(regional_factors).map{|cost,region_factor| cost * region_factor / 100.0}.inject(0, :+)
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
testSurfName = surface.name.to_s
|
|
125
|
-
testSpaceName = space.name.to_s
|
|
126
|
-
surfArea = surface.netArea * space.thermalZone.get.multiplier
|
|
127
|
-
surfAreaft = (OpenStudio.convert(surfArea, "m^2", "ft^2").get).to_f
|
|
128
|
-
surfCost = (cost + film_cost) * surfAreaft
|
|
129
|
-
totEnvCost = totEnvCost + surfCost
|
|
130
|
-
name = ""
|
|
131
|
-
|
|
132
|
-
# Bin the costing by construction standard type and rsi
|
|
133
|
-
if space.construction_set.nil?
|
|
134
|
-
name = "undefined space type_#{(1.0 / rsi).round(3)}"
|
|
135
|
-
else
|
|
136
|
-
name = "#{space.construction_set[surface_type]}"
|
|
137
|
-
end
|
|
138
|
-
row = @costing_report["envelope"]["construction_costs"].detect { |row| (row['name'] == name) && (row['conductance'].round(3) == ((1.0 / rsi).round(3))) }
|
|
139
|
-
if row.nil?
|
|
140
|
-
@costing_report["envelope"]["construction_costs"] << {'name' => name, 'conductance' => ((1.0 / rsi).round(3)), 'area' => (surfArea.round(2)), 'cost' => (surfCost.round(2)), 'cost_per_area' => (surfCost / surfArea).round(2), 'note' => "Surf ##{numSurfType}: #{notes}"}
|
|
141
|
-
else
|
|
142
|
-
# Not using += for @costing_report additions so that output can be properly rounded
|
|
143
|
-
row['area'] = (row['area'] + surfArea).round(2)
|
|
144
|
-
row['cost'] = (row['cost'] + surfCost).round(2)
|
|
145
|
-
row['cost_per_area'] = ((row['cost'] / row['area']).to_f.round(2))
|
|
146
|
-
row['note'] += " / #{numSurfType}: #{notes}"
|
|
147
|
-
end
|
|
148
|
-
# Not using += for @costing_report additions so that output can be properly rounded
|
|
149
|
-
@costing_report["envelope"]["#{surface_type.underscore}_cost"] = (@costing_report["envelope"]["#{surface_type.underscore}_cost"] + surfCost).round(2)
|
|
150
|
-
@costing_report["envelope"]["#{surface_type.underscore}_area_m2"] = (@costing_report["envelope"]["#{surface_type.underscore}_area_m2"] + surfArea).round(2)
|
|
151
|
-
@costing_report["envelope"]["#{surface_type.underscore}_cost_per_m2"] = (@costing_report["envelope"]["#{surface_type.underscore}_cost"] / @costing_report["envelope"]["#{surface_type.underscore}_area_m2"]).round(2)
|
|
152
|
-
end # surfaces of surface type
|
|
153
|
-
end # surface_type
|
|
154
|
-
end # spaces
|
|
155
|
-
|
|
156
|
-
@costing_report["envelope"]['total_envelope_cost'] = totEnvCost.to_f.round(2)
|
|
157
|
-
puts "\nEnvelope costing data successfully generated. Total envelope cost is $#{totEnvCost.to_f.round(2)}"
|
|
158
|
-
|
|
159
|
-
return totEnvCost
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
def cost_construction(construction, location, type = 'opaque')
|
|
163
|
-
|
|
164
|
-
material_layers = "material_#{type}_id_layers"
|
|
165
|
-
material_id = "materials_#{type}_id"
|
|
166
|
-
materials_database = @costing_database["raw"]["materials_#{type}"]
|
|
167
|
-
|
|
168
|
-
total_with_op = 0.0
|
|
169
|
-
material_cost_pairs = []
|
|
170
|
-
construction[material_layers].split(',').reject { |c| c.empty? }.each do |material_index|
|
|
171
|
-
material = materials_database.find { |data| data[material_id].to_s == material_index.to_s }
|
|
172
|
-
if material.nil?
|
|
173
|
-
puts "material error..could not find material #{material_index} in #{materials_database}"
|
|
174
|
-
raise()
|
|
175
|
-
else
|
|
176
|
-
costing_data = @costing_database['costs'].detect { |data| data['id'].to_s.upcase == material['id'].to_s.upcase }
|
|
177
|
-
if costing_data.nil?
|
|
178
|
-
puts "This material id #{material['id']} was not found in the costing database. Skipping. This construction will be inaccurate. "
|
|
179
|
-
raise()
|
|
180
|
-
else
|
|
181
|
-
regional_material, regional_installation = get_regional_cost_factors(location['province_state'], location['city'], material)
|
|
182
|
-
|
|
183
|
-
# Get cost information from lookup.
|
|
184
|
-
# Note that "glazing" types don't have a 'quantity' hash entry!
|
|
185
|
-
# Don't need "and" below but using in-case this hash field is added in the future.
|
|
186
|
-
if type == 'glazing' and material['quantity'].to_f == 0.0
|
|
187
|
-
material['quantity'] = '1.0'
|
|
188
|
-
end
|
|
189
|
-
material_cost = costing_data['baseCosts']['materialOpCost'].to_f * material['material_mult'].to_f
|
|
190
|
-
labour_cost = costing_data['baseCosts']['laborOpCost'].to_f * material['labour_mult'].to_f
|
|
191
|
-
equipment_cost = costing_data['baseCosts']['equipmentOpCost'].to_f
|
|
192
|
-
layer_cost = (((material_cost * regional_material / 100.0) + (labour_cost * regional_installation / 100.0) + equipment_cost) * material['quantity'].to_f).round(2)
|
|
193
|
-
material_cost_pairs << {material_id.to_s => material_index,
|
|
194
|
-
'cost' => layer_cost}
|
|
195
|
-
total_with_op += layer_cost
|
|
196
197
|
end
|
|
198
|
+
subset["cost"] = total_with_op
|
|
197
199
|
end
|
|
198
200
|
end
|
|
199
|
-
new_construction = {
|
|
200
|
-
'province_state' => location['province_state'],
|
|
201
|
-
'city' => location['city'],
|
|
202
|
-
"construction_type_name" => construction["construction_type_name"],
|
|
203
|
-
'description' => construction["description"],
|
|
204
|
-
'intended_surface_type' => construction["intended_surface_type"],
|
|
205
|
-
'standards_construction_type' => construction["standards_construction_type"],
|
|
206
|
-
'rsi_k_m2_per_w' => construction['rsi_k_m2_per_w'].to_f,
|
|
207
|
-
'zone' => construction['climate_zone'],
|
|
208
|
-
'fenestration_type' => construction['fenestration_type'],
|
|
209
|
-
'u_w_per_m2_k' => construction['u_w_per_m2_k'],
|
|
210
|
-
'materials' => material_cost_pairs,
|
|
211
|
-
'total_cost_with_op' => total_with_op}
|
|
212
|
-
|
|
213
|
-
@costing_database['constructions_costs'] << new_construction
|
|
214
201
|
end
|
|
215
|
-
end
|
|
202
|
+
end
|