diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule1.py b/rct229/rulesets/ashrae9012019/section5/section5rule1.py index c0fded905..9bdcae54e 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule1.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule1.py @@ -146,6 +146,12 @@ def __init__(self): required_fields={ "$.building_segments[*].zones[*].surfaces[*]": ["azimuth"], }, + precision={ + "percent_difference_max_min_fen_area_per_orientation": { + "precision": 0.01, + "unit": "", + } + }, fail_msg="Fail unless Table G3.1#5a exception #2 is applicable and it can be demonstrated that the building orientation is dictated by site considerations.", ) @@ -223,7 +229,13 @@ def get_key_for_azi(azi): ) rotation_expected_b = ( - percent_difference >= ACCEPTABLE_FEN_PERCENTAGE_DIFFERENCE + percent_difference > ACCEPTABLE_FEN_PERCENTAGE_DIFFERENCE + or self.precision_comparison[ + "percent_difference_max_min_fen_area_per_orientation" + ]( + percent_difference.magnitude, + ACCEPTABLE_FEN_PERCENTAGE_DIFFERENCE, + ) ) return { diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule10.py b/rct229/rulesets/ashrae9012019/section5/section5rule10.py index 919882cbb..c3fe89044 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule10.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule10.py @@ -80,6 +80,12 @@ def __init__(self): "$": ["construction"], "construction": ["u_factor"], }, + precision={ + "floor_u_factor_b": { + "precision": 0.001, + "unit": "Btu/(hr*ft2*R)", + } + }, ) def get_calc_vals(self, context, data=None): @@ -132,7 +138,11 @@ def manual_check_required(self, context, calc_vals=None, data=None): ) def rule_check(self, context, calc_vals=None, data=None): + return self.precision_comparison["floor_u_factor_b"]( + calc_vals["floor_u_factor"], calc_vals["target_u_factor"] + ) + + def is_tolerance_fail(self, context, calc_vals=None, data=None): floor_u_factor = calc_vals["floor_u_factor"] target_u_factor = calc_vals["target_u_factor"] - - return std_equal(val=floor_u_factor, std_val=target_u_factor) + return std_equal(floor_u_factor, target_u_factor) diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule12.py b/rct229/rulesets/ashrae9012019/section5/section5rule12.py index 2d730985f..0ae920be7 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule12.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule12.py @@ -91,6 +91,12 @@ def __init__(self): }, manual_check_required_msg=MANUAL_CHECK_REQUIRED_MSG, fail_msg=FAIL_MSG, + precision={ + "floor_f_factor_b": { + "precision": 0.001, + "unit": "Btu/(hr*ft*R)", + } + }, ) def get_calc_vals(self, context, data=None): @@ -147,9 +153,14 @@ def manual_check_required(self, context, calc_vals=None, data=None): return target_f_factor_res != target_f_factor_nonres def rule_check(self, context, calc_vals=None, data=None): + return self.precision_comparison["floor_f_factor_b"]( + calc_vals["target_f_factor"], + calc_vals["slab_on_grade_floor_f_factor"], + ) + + def is_tolerance_fail(self, context, calc_vals=None, data=None): target_f_factor = calc_vals["target_f_factor"] slab_on_grade_floor_f_factor = calc_vals["slab_on_grade_floor_f_factor"] - return std_equal( std_val=target_f_factor, val=slab_on_grade_floor_f_factor ) diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule13.py b/rct229/rulesets/ashrae9012019/section5/section5rule13.py index 562ad1c86..3d31adce7 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule13.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule13.py @@ -16,7 +16,6 @@ ) from rct229.utils.assertions import getattr_ from rct229.utils.pint_utils import CalcQ -from rct229.utils.std_comparisons import std_equal class Section5Rule13(RuleDefinitionListIndexedBase): @@ -76,6 +75,20 @@ def __init__(self): USER=False, BASELINE_0=True, PROPOSED=True ), required_fields={"$": ["construction"]}, + precision={ + "surface_u_factor_b": { + "precision": 0.001, + "unit": "Btu/(hr*ft2*R)", + }, + "surface_c_factor_b": { + "precision": 0.001, + "unit": "Btu/(hr*ft2*R)", + }, + "surface_f_factor_b": { + "precision": 0.001, + "unit": "Btu/(hr*ft*R)", + }, + }, ) def get_calc_vals(self, context, data=None): @@ -157,17 +170,20 @@ def rule_check(self, context, calc_vals=None, data=None): return False if baseline_surface_type in [OST.ABOVE_GRADE_WALL, OST.FLOOR, OST.ROOF]: - return std_equal( + return self.precision_comparison["surface_u_factor_b"]( calc_vals["baseline_surface_u_factor"], calc_vals["proposed_surface_u_factor"], ) + elif baseline_surface_type in [OST.UNHEATED_SOG, OST.HEATED_SOG]: - return std_equal( + return self.precision_comparison["surface_f_factor_b"]( calc_vals["baseline_surface_f_factor"], calc_vals["proposed_surface_f_factor"], ) + elif baseline_surface_type == OST.BELOW_GRADE_WALL: - return std_equal( + + return self.precision_comparison["surface_c_factor_b"]( calc_vals["baseline_surface_c_factor"], calc_vals["proposed_surface_c_factor"], ) diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule14.py b/rct229/rulesets/ashrae9012019/section5/section5rule14.py index eec132c5f..3898548e8 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule14.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule14.py @@ -110,6 +110,12 @@ def __init__(self): rmds_used=produce_ruleset_model_description( USER=False, BASELINE_0=True, PROPOSED=False ), + precision={ + "area_type_wwr_b": { + "precision": 0.01, + "unit": "", + } + }, ) def get_calc_vals(self, context, data=None): @@ -156,6 +162,12 @@ def get_manual_check_required_msg(self, context, calc_vals=None, data=None): return manual_check_msg def rule_check(self, context, calc_vals=None, data=None): + return self.precision_comparison["area_type_wwr_b"]( + calc_vals["area_type_wwr"].magnitude, + calc_vals["area_type_target_wwr"], + ) + + def is_tolerance_fail(self, context, calc_vals=None, data=None): area_type_wwr = calc_vals["area_type_wwr"] area_type_target_wwr = calc_vals["area_type_target_wwr"] - return std_equal(area_type_target_wwr, area_type_wwr) + return std_equal(area_type_wwr, area_type_target_wwr) diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule15.py b/rct229/rulesets/ashrae9012019/section5/section5rule15.py index 9a51489e1..3f6fc29c3 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule15.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule15.py @@ -53,6 +53,12 @@ def __init__(self): "area_type_vertical_fenestration", ], }, + precision={ + "wwr_b": { + "precision": 0.01, + "unit": "", + } + }, ) def is_applicable(self, context, data=None): @@ -109,6 +115,10 @@ def get_manual_check_required_msg(self, context, calc_vals=None, data=None): return manual_check_msg def rule_check(self, context, calc_vals=None, data=None): - return not calc_vals["manual_check_flag"] and std_equal( - calc_vals["wwr_b"], min(calc_vals["wwr_p"], WWR_THRESHOLD) + return self.precision_comparison["wwr_b"]( + calc_vals["wwr_b"].magnitude, + min(calc_vals["wwr_p"].magnitude, WWR_THRESHOLD), ) + + def is_tolerance_fail(self, context, calc_vals=None, data=None): + return std_equal(calc_vals["wwr_b"], min(calc_vals["wwr_p"], WWR_THRESHOLD)) diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule16.py b/rct229/rulesets/ashrae9012019/section5/section5rule16.py index d71e0a67b..b33964eb9 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule16.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule16.py @@ -109,6 +109,12 @@ def __init__(self): "$": ["construction"], "construction": ["u_factor"], }, + precision={ + "total_fenestration_area_surface_b / total_fenstration_area_b": { + "precision": 0.01, + "unit": "", + } + }, fail_msg=FAIL_MSG, ) @@ -169,7 +175,17 @@ def rule_check(self, context, calc_vals=None, data=None): return ( total_fenestration_area_b == ZERO.AREA and total_fenestration_area_p == ZERO.AREA - ) or std_equal( - (total_fenestration_area_surface_b / total_fenestration_area_b), - (total_fenestration_area_surface_p / total_fenestration_area_p), + ) or ( + self.precision_comparison[ + "total_fenestration_area_surface_b / total_fenstration_area_b" + ]( + ( + total_fenestration_area_surface_b + / total_fenestration_area_b + ).magnitude, + ( + total_fenestration_area_surface_p + / total_fenestration_area_p + ).magnitude, + ) ) diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule19.py b/rct229/rulesets/ashrae9012019/section5/section5rule19.py index 6000dc7a7..89204ff05 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule19.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule19.py @@ -2,6 +2,7 @@ from rct229.rule_engine.rule_list_indexed_base import RuleDefinitionListIndexedBase from rct229.rule_engine.ruleset_model_factory import produce_ruleset_model_description from rct229.rulesets.ashrae9012019 import BASELINE_0 +from rct229.schema.schema_enums import SchemaEnums from rct229.rulesets.ashrae9012019.data_fns.table_G3_4_fns import table_G34_lookup from rct229.rulesets.ashrae9012019.ruleset_functions.get_building_scc_window_wall_ratios_dict import ( get_building_scc_window_wall_ratios_dict, @@ -18,7 +19,6 @@ from rct229.rulesets.ashrae9012019.ruleset_functions.get_surface_conditioning_category_dict import ( get_surface_conditioning_category_dict, ) -from rct229.schema.schema_enums import SchemaEnums from rct229.utils.jsonpath_utils import find_all from rct229.utils.pint_utils import ZERO, CalcQ from rct229.utils.std_comparisons import std_equal @@ -264,6 +264,12 @@ def __init__(self): rmds_used=produce_ruleset_model_description( USER=False, BASELINE_0=True, PROPOSED=False ), + precision={ + "subsurface_u_factor_b": { + "precision": 0.01, + "unit": "Btu/(hr*ft2*R)", + } + }, ) def get_calc_vals(self, context, data=None): @@ -293,6 +299,11 @@ def get_calc_vals(self, context, data=None): } def rule_check(self, context, calc_vals=None, data=None): + return self.precision_comparison["subsurface_u_factor_b"]( + calc_vals["target_u_factor"], calc_vals["subsurface_u_factor"] + ) + + def is_tolerance_fail(self, context, calc_vals=None, data=None): target_u_factor = calc_vals["target_u_factor"] subsurface_u_factor = calc_vals["subsurface_u_factor"] return std_equal(std_val=target_u_factor, val=subsurface_u_factor) diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule20.py b/rct229/rulesets/ashrae9012019/section5/section5rule20.py index 58f49c7f2..c536f1552 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule20.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule20.py @@ -251,6 +251,12 @@ def __init__(self): rmds_used=produce_ruleset_model_description( USER=False, BASELINE_0=True, PROPOSED=False ), + precision={ + "subsurface_shgc_b": { + "precision": 0.01, + "unit": "", + } + }, ) def manual_check_required(self, context, calc_vals=None, data=None): @@ -282,6 +288,14 @@ def get_calc_vals(self, context, data=None): def rule_check(self, context, calc_vals=None, data=None): target_shgc = calc_vals["target_shgc"] subsurface_shgc = calc_vals["subsurface_shgc"] + + return target_shgc is not None and self.precision_comparison[ + "subsurface_shgc_b" + ](subsurface_shgc, target_shgc) + + def is_tolerance_fail(self, context, calc_vals=None, data=None): + target_shgc = calc_vals["target_shgc"] + subsurface_shgc = calc_vals["subsurface_shgc"] return target_shgc is not None and std_equal( std_val=target_shgc, val=subsurface_shgc ) diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule21.py b/rct229/rulesets/ashrae9012019/section5/section5rule21.py index d998cf274..f3ba1514b 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule21.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule21.py @@ -9,7 +9,7 @@ get_surface_conditioning_category_dict, ) from rct229.utils.pint_utils import CalcQ -from rct229.utils.std_comparisons import std_equal + FAIL_MSG = "Subsurface that is not regulated (Not part of building envelope) is not modeled with the same area, U-factor and SHGC in the baseline as in the propsoed design." @@ -83,22 +83,25 @@ def __init__(self): rmds_used=produce_ruleset_model_description( USER=False, BASELINE_0=True, PROPOSED=True ), - fail_msg=FAIL_MSG, precision={ "subsurface_u_factor_b": { - "precision": 0.000000001, + "precision": 0.01, "unit": "Btu/(hr*ft2*R)", }, - "subsurface_shgc_b": {"precision": 0.000000000001}, + "subsurface_shgc_b": { + "precision": 0.01, + "unit": "", + }, "subsurface_glazed_area_b": { - "precision": 0.000000000001, + "precision": 1, "unit": "ft2", }, "subsurface_opaque_area_b": { - "precision": 0.000000000001, + "precision": 1, "unit": "ft2", }, }, + fail_msg=FAIL_MSG, ) def get_calc_vals(self, context, data=None): diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule23.py b/rct229/rulesets/ashrae9012019/section5/section5rule23.py index 9737ba89e..242df1c37 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule23.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule23.py @@ -3,6 +3,7 @@ from rct229.rule_engine.ruleset_model_factory import produce_ruleset_model_description from rct229.rulesets.ashrae9012019 import BASELINE_0 from rct229.utils.jsonpath_utils import find_all +from rct229.utils.std_comparisons import std_equal MANUAL_CHECK_MSG = "Surface in P-RMD has subsurfaces modeled with different manual shade status. Verify if subsurfaces manual shade status in B-RMD are modeled the same as in P-RMD" diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule24.py b/rct229/rulesets/ashrae9012019/section5/section5rule24.py index a8186d4a4..e74c53bf2 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule24.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule24.py @@ -63,6 +63,12 @@ def __init__(self): rmds_used=produce_ruleset_model_description( USER=False, BASELINE_0=True, PROPOSED=True ), + precision={ + "skylight_roof_ratio_b": { + "precision": 0.01, + "unit": "", + } + }, ) def is_applicable(self, context, data=None): @@ -112,6 +118,7 @@ def get_calc_vals(self, context, data=None): } def rule_check(self, context, calc_vals=None, data=None): - skylight_roof_ratio_b = calc_vals["skylight_roof_ratio_b"] - skylight_roof_ratio_p = calc_vals["skylight_total_roof_ratio_p"] - return std_equal(skylight_roof_ratio_b, skylight_roof_ratio_p) + return self.precision_comparison["skylight_roof_ratio_b"]( + calc_vals["skylight_roof_ratio_b"].magnitude, + calc_vals["skylight_total_roof_ratio_p"].magnitude, + ) diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule25.py b/rct229/rulesets/ashrae9012019/section5/section5rule25.py index bdb508411..6a05ab73c 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule25.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule25.py @@ -63,6 +63,12 @@ def __init__(self): rmds_used=produce_ruleset_model_description( USER=False, BASELINE_0=True, PROPOSED=True ), + precision={ + "skylight_roof_ratio_b": { + "precision": 0.01, + "unit": "", + } + }, ) def is_applicable(self, context, data=None): @@ -110,5 +116,10 @@ def get_calc_vals(self, context, data=None): } def rule_check(self, context, calc_vals=None, data=None): + return self.precision_comparison["skylight_roof_ratio_b"]( + calc_vals["skylight_roof_ratio_b"].magnitude, SKYLIGHT_THRESHOLD + ) + + def is_tolerance_fail(self, context, calc_vals=None, data=None): skylight_roof_ratio_b = calc_vals["skylight_roof_ratio_b"] - return std_equal(skylight_roof_ratio_b, 0.03) + return std_equal(skylight_roof_ratio_b, SKYLIGHT_THRESHOLD) diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule26.py b/rct229/rulesets/ashrae9012019/section5/section5rule26.py index f7cda7017..101ddf2df 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule26.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule26.py @@ -131,6 +131,12 @@ def __init__(self): rmds_used=produce_ruleset_model_description( USER=False, BASELINE_0=True, PROPOSED=True ), + precision={ + "total_skylight_area_surface_b / total_skylight_area_b": { + "precision": 0.01, + "unit": "", + } + }, ) def get_calc_vals(self, context, data=None): @@ -188,8 +194,14 @@ def rule_check(self, context, calc_vals=None, data=None): # product to ensure neither is 0 & short-circuit logic if either of them is 0. total_skylight_area_b * total_skylight_area_p > 0 # both segments' skylight area ratios are the same - and std_equal( - total_skylight_area_surface_b / total_skylight_area_b, - total_skylight_area_surface_p / total_skylight_area_p, + and self.precision_comparison[ + "total_skylight_area_surface_b / total_skylight_area_b" + ]( + ( + total_skylight_area_surface_b / total_skylight_area_b + ).magnitude, + ( + total_skylight_area_surface_p / total_skylight_area_p + ).magnitude, ) ) diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule27.py b/rct229/rulesets/ashrae9012019/section5/section5rule27.py index 31ae771d6..8520e3080 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule27.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule27.py @@ -2,6 +2,7 @@ from rct229.rule_engine.rule_list_indexed_base import RuleDefinitionListIndexedBase from rct229.rule_engine.ruleset_model_factory import produce_ruleset_model_description from rct229.rulesets.ashrae9012019 import BASELINE_0 +from rct229.schema.schema_enums import SchemaEnums from rct229.rulesets.ashrae9012019.data_fns.table_G3_4_fns import table_G34_lookup from rct229.rulesets.ashrae9012019.ruleset_functions.get_building_scc_skylight_roof_ratios_dict import ( get_building_scc_skylight_roof_ratios_dict, @@ -18,7 +19,6 @@ from rct229.rulesets.ashrae9012019.ruleset_functions.get_surface_conditioning_category_dict import ( get_surface_conditioning_category_dict, ) -from rct229.schema.schema_enums import SchemaEnums from rct229.utils.pint_utils import ZERO, CalcQ from rct229.utils.std_comparisons import std_equal @@ -227,6 +227,12 @@ def __init__(self): "u_factor", ] }, + precision={ + "subsurface_u_factor_b": { + "precision": 0.01, + "unit": "Btu/(hr*ft2*R)", + } + }, ) def is_applicable(self, context, data=None): @@ -265,6 +271,11 @@ def get_calc_vals(self, context, data=None): } def rule_check(self, context, calc_vals=None, data=None): + return self.precision_comparison["subsurface_u_factor_b"]( + calc_vals["subsurface_b_u_factor"], calc_vals["target_u_factor"] + ) + + def is_tolerance_fail(self, context, calc_vals=None, data=None): subsurface_b_u_factor = calc_vals["subsurface_b_u_factor"] target_u_factor = calc_vals["target_u_factor"] - return std_equal(std_val=target_u_factor, val=subsurface_b_u_factor) + return std_equal(target_u_factor, subsurface_b_u_factor) diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule28.py b/rct229/rulesets/ashrae9012019/section5/section5rule28.py index f6c91a2ec..4cd7f56f9 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule28.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule28.py @@ -196,6 +196,12 @@ def __init__(self): required_fields={ "$": ["classification", "glazed_area", "opaque_area"] }, + precision={ + "subsurface_shgc_b": { + "precision": 0.01, + "unit": "", + } + }, ) def is_applicable(self, context, data=None): @@ -240,7 +246,11 @@ def get_calc_vals(self, context, data=None): } def rule_check(self, context, calc_vals=None, data=None): + return self.precision_comparison["subsurface_shgc_b"]( + calc_vals["subsurface_shgc_b"], calc_vals["target_shgc"] + ) + + def is_tolerance_fail(self, context, calc_vals=None, data=None): target_shgc = calc_vals["target_shgc"] subsurface_shgc_b = calc_vals["subsurface_shgc_b"] - return std_equal(target_shgc, subsurface_shgc_b) diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule29.py b/rct229/rulesets/ashrae9012019/section5/section5rule29.py index 5fe04f2d0..63ff716ee 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule29.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule29.py @@ -78,6 +78,12 @@ def __init__(self): "$": ["optical_properties"], "optical_properties": ["absorptance_thermal_exterior"], }, + precision={ + "absorptance_thermal_exterior_b": { + "precision": 0.01, + "unit": "", + } + }, ) def get_calc_vals(self, context, data=None): @@ -89,6 +95,12 @@ def get_calc_vals(self, context, data=None): } def rule_check(self, context, calc_vals=None, data=None): + return self.precision_comparison["absorptance_thermal_exterior_b"]( + calc_vals["absorptance_thermal_exterior"], + TARGET_ABSORPTANCE_THERMAL_EXTERIOR, + ) + + def is_tolerance_fail(self, context, calc_vals=None, data=None): return std_equal( TARGET_ABSORPTANCE_THERMAL_EXTERIOR, calc_vals["absorptance_thermal_exterior"], diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule30.py b/rct229/rulesets/ashrae9012019/section5/section5rule30.py index cfff84ffe..3e0d9997f 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule30.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule30.py @@ -14,6 +14,7 @@ from rct229.rulesets.ashrae9012019.ruleset_functions.get_surface_conditioning_category_dict import ( get_surface_conditioning_category_dict, ) +from rct229.utils.std_comparisons import std_equal ABSORPTION_THERMAL_EXTERIOR = 0.9 UNDETERMINED_MSG = ( @@ -83,6 +84,12 @@ def __init__(self): "$": ["optical_properties"], "optical_properties": ["absorptance_thermal_exterior"], }, + precision={ + "absorptance_thermal_exterior_p": { + "precision": 0.01, + "unit": "", + } + }, ) def get_calc_vals(self, context, data=None): @@ -119,9 +126,9 @@ def get_manual_check_required_msg(self, context, calc_vals=None, data=None): ) def rule_check(self, context, calc_vals=None, data=None): - return ( - calc_vals["absorptance_thermal_exterior_p"] - == ABSORPTION_THERMAL_EXTERIOR + return self.precision_comparison["absorptance_thermal_exterior_p"]( + calc_vals["absorptance_thermal_exterior_p"], + ABSORPTION_THERMAL_EXTERIOR, ) def get_pass_msg(self, context, calc_vals=None, data=None): @@ -142,3 +149,9 @@ def get_pass_msg(self, context, calc_vals=None, data=None): ) return pass_msg + + def is_tolerance_fail(self, context, calc_vals=None, data=None): + return std_equal( + calc_vals["absorptance_thermal_exterior_p"], + ABSORPTION_THERMAL_EXTERIOR, + ) diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule31.py b/rct229/rulesets/ashrae9012019/section5/section5rule31.py index f57412fdd..369e4c926 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule31.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule31.py @@ -78,6 +78,12 @@ def __init__(self): "$": ["optical_properties"], "optical_properties": ["absorptance_solar_exterior"], }, + precision={ + "absorptance_solar_exterior_b": { + "precision": 0.01, + "unit": "", + } + }, ) def get_calc_vals(self, context, data=None): @@ -89,6 +95,12 @@ def get_calc_vals(self, context, data=None): } def rule_check(self, context, calc_vals=None, data=None): + return self.precision_comparison["absorptance_solar_exterior_b"]( + calc_vals["absorptance_solar_exterior"], + TARGET_ABSORPTANCE_SOLAR_EXTERIOR, + ) + + def is_tolerance_fail(self, context, calc_vals=None, data=None): return std_equal( TARGET_ABSORPTANCE_SOLAR_EXTERIOR, calc_vals["absorptance_solar_exterior"], diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule32.py b/rct229/rulesets/ashrae9012019/section5/section5rule32.py index 6d460566d..8add039bf 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule32.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule32.py @@ -14,6 +14,7 @@ from rct229.rulesets.ashrae9012019.ruleset_functions.get_surface_conditioning_category_dict import ( get_surface_conditioning_category_dict, ) +from rct229.utils.std_comparisons import std_equal ABSORPTANCE_SOLAR_EXTERIOR = 0.7 @@ -78,6 +79,12 @@ def __init__(self): "$": ["optical_properties"], "optical_properties": ["absorptance_solar_exterior"], }, + precision={ + "absorptance_solar_exterior_p": { + "precision": 0.01, + "unit": "", + } + }, ) def get_calc_vals(self, context, data=None): @@ -110,9 +117,15 @@ def get_manual_check_required_msg(self, context, calc_vals=None, data=None): ) def rule_check(self, context, calc_vals=None, data=None): - return ( - calc_vals["absorptance_solar_exterior_p"] - == ABSORPTANCE_SOLAR_EXTERIOR + return self.precision_comparison["absorptance_solar_exterior_p"]( + calc_vals["absorptance_solar_exterior_p"], + ABSORPTANCE_SOLAR_EXTERIOR, + ) + + def is_tolerance_fail(self, context, calc_vals=None, data=None): + return std_equal( + calc_vals["absorptance_solar_exterior_p"], + ABSORPTANCE_SOLAR_EXTERIOR, ) def get_pass_msg(self, context, calc_vals=None, data=None): diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule35.py b/rct229/rulesets/ashrae9012019/section5/section5rule35.py index c9ce92f6d..3a4599772 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule35.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule35.py @@ -54,6 +54,12 @@ def __init__(self): USER=False, BASELINE_0=True, PROPOSED=False ), required_fields={"$.building_segments[*].zones[*]": ["surfaces"]}, + precision={ + "building_total_air_leakage_rate": { + "precision": 1, + "unit": "cfm", + } + }, ) def get_calc_vals(self, context, data=None): @@ -96,14 +102,20 @@ def get_calc_vals(self, context, data=None): return { "building_total_air_leakage_rate": CalcQ( - "volumetric_flow_rate", building_total_air_leakage_rate + "air_flow_rate", building_total_air_leakage_rate ), "target_air_leakage_rate_75pa_b": CalcQ( - "volumetric_flow_rate", target_air_leakage_rate_75pa_b + "air_flow_rate", target_air_leakage_rate_75pa_b ), } def rule_check(self, context, calc_vals=None, data=None): + return self.precision_comparison["building_total_air_leakage_rate"]( + calc_vals["building_total_air_leakage_rate"], + calc_vals["target_air_leakage_rate_75pa_b"] * TOTAL_AIR_LEAKAGE_FACTOR, + ) + + def is_tolerance_fail(self, context, calc_vals=None, data=None): building_total_air_leakage_rate = calc_vals[ "building_total_air_leakage_rate" ] diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule36.py b/rct229/rulesets/ashrae9012019/section5/section5rule36.py index 8309d472a..1be7444db 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule36.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule36.py @@ -71,6 +71,12 @@ def __init__(self): "$": ["infiltration"], "infiltration": ["flow_rate"], }, + precision={ + "total_infiltration_rate_b": { + "precision": 0.1, + "unit": "cfm", + } + }, ) def get_calc_vals(self, context, data=None): @@ -82,15 +88,15 @@ def get_calc_vals(self, context, data=None): return { "baseline_infiltration": CalcQ( - "volumetric_flow_rate", zone_infiltration_flow_rate_b + "air_flow_rate", zone_infiltration_flow_rate_b ), "proposed_infiltration": CalcQ( - "volumetric_flow_rate", zone_infiltration_flow_rate_p + "air_flow_rate", zone_infiltration_flow_rate_p ), } def rule_check(self, context, calc_vals=None, data=None): - return ( - calc_vals["baseline_infiltration"] - == calc_vals["proposed_infiltration"] + return self.precision_comparison["total_infiltration_rate_b"]( + calc_vals["baseline_infiltration"], + calc_vals["proposed_infiltration"], ) diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule37.py b/rct229/rulesets/ashrae9012019/section5/section5rule37.py index c22800ed1..1b039c038 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule37.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule37.py @@ -57,6 +57,12 @@ def __init__(self): USER=False, BASELINE_0=False, PROPOSED=True ), required_fields={"$..zones[*]": ["surfaces"]}, + precision={ + "building_total_air_leakage_rate_b": { + "precision": 1, + "unit": "cfm", + } + }, ) def get_calc_vals(self, context, data=None): @@ -109,13 +115,13 @@ def get_calc_vals(self, context, data=None): return { "building_total_air_leakage_rate": CalcQ( - "volumetric_flow_rate", building_total_air_leakage_rate + "air_flow_rate", building_total_air_leakage_rate ), "building_total_measured_air_leakage_rate": CalcQ( - "volumetric_flow_rate", building_total_measured_air_leakage_rate + "air_flow_rate", building_total_measured_air_leakage_rate ), "target_air_leakage_rate_75pa_p": CalcQ( - "volumetric_flow_rate", target_air_leakage_rate_75pa_p + "air_flow_rate", target_air_leakage_rate_75pa_p ), "empty_measured_air_leakage_rate_flow_flag": empty_measured_air_leakage_rate_flow_flag, } @@ -130,7 +136,7 @@ def manual_check_required(self, context, calc_vals=None, data=None): ] return ( - not std_equal( + not self.precision_comparison["building_total_air_leakage_rate_b"]( building_total_air_leakage_rate, TOTAL_AIR_LEAKAGE_COEFF * target_air_leakage_rate_75pa_p, ) @@ -149,15 +155,38 @@ def rule_check(self, context, calc_vals=None, data=None): "empty_measured_air_leakage_rate_flow_flag" ] - return std_equal( + return self.precision_comparison["building_total_air_leakage_rate_b"]( building_total_air_leakage_rate, TOTAL_AIR_LEAKAGE_COEFF * target_air_leakage_rate_75pa_p, ) or ( - building_total_air_leakage_rate - != TOTAL_AIR_LEAKAGE_COEFF * target_air_leakage_rate_75pa_p - and empty_measured_air_leakage_rate_flow_flag == False - and std_equal( + empty_measured_air_leakage_rate_flow_flag == False + and self.precision_comparison["building_total_air_leakage_rate_b"]( building_total_air_leakage_rate, TOTAL_AIR_LEAKAGE_COEFF * building_total_measured_air_leakage_rate, ) ) + + def is_tolerance_fail(self, context, calc_vals=None, data=None): + building_total_air_leakage_rate = calc_vals[ + "building_total_air_leakage_rate" + ] + building_total_measured_air_leakage_rate = calc_vals[ + "building_total_measured_air_leakage_rate" + ] + target_air_leakage_rate_75pa_p = calc_vals["target_air_leakage_rate_75pa_p"] + empty_measured_air_leakage_rate_flow_flag = calc_vals[ + "empty_measured_air_leakage_rate_flow_flag" + ] + + return std_equal( + building_total_air_leakage_rate, + TOTAL_AIR_LEAKAGE_COEFF * target_air_leakage_rate_75pa_p, + ) or ( + not std_equal( + building_total_air_leakage_rate, + TOTAL_AIR_LEAKAGE_COEFF * target_air_leakage_rate_75pa_p, + ) + and empty_measured_air_leakage_rate_flow_flag == False + and building_total_air_leakage_rate + == TOTAL_AIR_LEAKAGE_COEFF * building_total_measured_air_leakage_rate + ) diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule39.py b/rct229/rulesets/ashrae9012019/section5/section5rule39.py index 8291a3fc3..523a356f6 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule39.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule39.py @@ -110,6 +110,12 @@ def __init__(self): required_fields={ "$": ["subclassification", "u_factor"], }, + precision={ + "subsurface_u_factor_b": { + "precision": 0.01, + "unit": "Btu/(hr*ft2*R)", + } + }, ) def get_calc_vals(self, context, data=None): @@ -223,6 +229,11 @@ def get_manual_check_required_msg( return manual_check_required_msg def rule_check(self, context, calc_vals=None, data=None): + return self.precision_comparison["subsurface_u_factor_b"]( + calc_vals["u_factor_b"], calc_vals["target_u_factor_b"] + ) + + def is_tolerance_fail(self, context, calc_vals=None, data=None): u_factor_b = calc_vals["u_factor_b"] target_u_factor_b = calc_vals["target_u_factor_b"] return std_equal(target_u_factor_b, u_factor_b) diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule4.py b/rct229/rulesets/ashrae9012019/section5/section5rule4.py index 8b2048900..b3dbd1bfb 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule4.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule4.py @@ -81,6 +81,12 @@ def __init__(self): "$": ["construction"], "construction": ["u_factor"], }, + precision={ + "roof_u_factor_b": { + "precision": 0.001, + "unit": "Btu/(hr*ft2*R)", + } + }, ) def get_calc_vals(self, context, data=None): @@ -133,7 +139,11 @@ def manual_check_required(self, context=None, calc_vals=None, data=None): ) def rule_check(self, context=None, calc_vals=None, data=None): + return self.precision_comparison["roof_u_factor_b"]( + calc_vals["roof_u_factor"], calc_vals["target_u_factor"] + ) + + def is_tolerance_fail(self, context, calc_vals=None, data=None): roof_u_factor = calc_vals["roof_u_factor"] target_u_factor = calc_vals["target_u_factor"] - - return std_equal(val=roof_u_factor, std_val=target_u_factor) + return std_equal(roof_u_factor, target_u_factor) diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule40.py b/rct229/rulesets/ashrae9012019/section5/section5rule40.py index 57c9bcb88..3142b113f 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule40.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule40.py @@ -15,6 +15,7 @@ get_surface_conditioning_category_dict, ) from rct229.utils.jsonpath_utils import find_one +from rct229.utils.std_comparisons import std_equal class Section5Rule40(RuleDefinitionListIndexedBase): @@ -71,6 +72,16 @@ def __init__(self): rmds_used=produce_ruleset_model_description( USER=False, BASELINE_0=True, PROPOSED=True ), + precision={ + "absorptance_thermal_exterior_b": { + "precision": 0.01, + "unit": "", + }, + "absorptance_solar_exterior_b": { + "precision": 0.01, + "unit": "", + }, + }, ) def get_calc_vals(self, context, data=None): @@ -119,7 +130,8 @@ def rule_check(self, context, calc_vals=None, data=None): absorptance_thermal_exterior_p = calc_vals[ "absorptance_thermal_exterior_p" ] - return ( - absorptance_solar_exterior_b == absorptance_solar_exterior_p - and absorptance_thermal_exterior_b == absorptance_thermal_exterior_p + return self.precision_comparison["absorptance_solar_exterior_b"]( + absorptance_solar_exterior_b, absorptance_solar_exterior_p + ) and self.precision_comparison["absorptance_thermal_exterior_b"]( + absorptance_thermal_exterior_b, absorptance_thermal_exterior_p ) diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule6.py b/rct229/rulesets/ashrae9012019/section5/section5rule6.py index f378e59df..29bb95e93 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule6.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule6.py @@ -80,6 +80,12 @@ def __init__(self): "$": ["construction"], "construction": ["c_factor"], }, + precision={ + "bg_wall_c_factor_b": { + "precision": 0.001, + "unit": "Btu/(hr*ft2*R)", + } + }, ) def get_calc_vals(self, context, data=None): @@ -136,7 +142,11 @@ def manual_check_required(self, context, calc_vals=None, data=None): ) def rule_check(self, context, calc_vals=None, data=None): + return self.precision_comparison["bg_wall_c_factor_b"]( + calc_vals["below_grade_wall_c_factor"], calc_vals["target_c_factor"] + ) + + def is_tolerance_fail(self, context, calc_vals=None, data=None): below_grade_wall_c_factor = calc_vals["below_grade_wall_c_factor"] target_c_factor = calc_vals["target_c_factor"] - - return std_equal(val=below_grade_wall_c_factor, std_val=target_c_factor) + return std_equal(below_grade_wall_c_factor, target_c_factor) diff --git a/rct229/rulesets/ashrae9012019/section5/section5rule8.py b/rct229/rulesets/ashrae9012019/section5/section5rule8.py index 2ba78e665..816e161f4 100644 --- a/rct229/rulesets/ashrae9012019/section5/section5rule8.py +++ b/rct229/rulesets/ashrae9012019/section5/section5rule8.py @@ -77,6 +77,12 @@ def __init__(self): USER=False, BASELINE_0=True, PROPOSED=False ), required_fields={}, + precision={ + "ag_wall_u_factor_b": { + "precision": 0.001, + "unit": "Btu/(hr*ft2*R)", + } + }, ) def get_calc_vals(self, context, data=None): @@ -129,7 +135,11 @@ def manual_check_required(self, context, calc_vals=None, data=None): return target_u_factor_res != target_u_factor_nonres def rule_check(self, context, calc_vals=None, data=None): + return self.precision_comparison["ag_wall_u_factor_b"]( + calc_vals["above_grade_wall_u_factor"], calc_vals["target_u_factor"] + ) + + def is_tolerance_fail(self, context, calc_vals=None, data=None): above_grade_wall_u_factor = calc_vals["above_grade_wall_u_factor"] target_u_factor = calc_vals["target_u_factor"] - - return std_equal(val=above_grade_wall_u_factor, std_val=target_u_factor) + return std_equal(above_grade_wall_u_factor, target_u_factor) diff --git a/rct229/rulesets/ashrae9012019/section6/section6rule1.py b/rct229/rulesets/ashrae9012019/section6/section6rule1.py index 20b3aea0c..f37ac493b 100644 --- a/rct229/rulesets/ashrae9012019/section6/section6rule1.py +++ b/rct229/rulesets/ashrae9012019/section6/section6rule1.py @@ -40,6 +40,16 @@ def __init__(self): USER=False, BASELINE_0=False, PROPOSED=True ), required_fields={"$.zones[*]": ["volume"]}, + precision={ + "building_segment_design_lighting_wattage_area": { + "precision": 0.01, + "unit": "W", + }, + "building_segment_design_lighting_wattage_space": { + "precision": 0.01, + "unit": "W", + }, + }, ) def get_calc_vals(self, context, data=None): @@ -118,10 +128,22 @@ def rule_check(self, context, calc_vals=None, data=None): return ( (allowable_LPD_BAM or not check_BAM_flag) - and building_segment_design_lighting_wattage - <= allowable_LPD_wattage_BAM - or building_segment_design_lighting_wattage - <= allowable_lighting_wattage_SBS + and ( + building_segment_design_lighting_wattage < allowable_LPD_wattage_BAM + ) + or self.precision_comparison[ + "building_segment_design_lighting_wattage_area" + ](building_segment_design_lighting_wattage, allowable_LPD_wattage_BAM) + or ( + building_segment_design_lighting_wattage + < allowable_lighting_wattage_SBS + or self.precision_comparison[ + "building_segment_design_lighting_wattage_space" + ]( + building_segment_design_lighting_wattage, + allowable_lighting_wattage_SBS, + ) + ) ) def get_pass_msg(self, context, calc_vals=None, data=None): diff --git a/rct229/rulesets/ashrae9012019/section6/section6rule2.py b/rct229/rulesets/ashrae9012019/section6/section6rule2.py index 91b088bd1..d71ca76d5 100644 --- a/rct229/rulesets/ashrae9012019/section6/section6rule2.py +++ b/rct229/rulesets/ashrae9012019/section6/section6rule2.py @@ -7,6 +7,7 @@ from rct229.schema.schema_enums import SchemaEnums from rct229.utils.jsonpath_utils import find_all from rct229.utils.pint_utils import ZERO, CalcQ +from rct229.utils.std_comparisons import std_equal GUEST_ROOM = SchemaEnums.schema_enums[ "LightingSpaceOptions2019ASHRAE901TG37" @@ -61,6 +62,12 @@ def __init__(self): "$": ["interior_lighting"], "interior_lighting[*]": ["power_per_area"], }, + precision={ + "space_lighting_power_per_area_p": { + "precision": 0.01, + "unit": "W/ft2", + } + }, ) def is_applicable(self, context, data=None): @@ -113,6 +120,21 @@ def rule_check(self, context, calc_vals=None, data=None): "space_lighting_power_per_area_u" ] - return space_lighting_power_per_area_p == max( - lighting_power_allowance_p, space_lighting_power_per_area_u + return self.precision_comparison["space_lighting_power_per_area_p"]( + space_lighting_power_per_area_p, + max(lighting_power_allowance_p, space_lighting_power_per_area_u), + ) + + def is_tolerance_fail(self, context, calc_vals=None, data=None): + lighting_power_allowance_p = calc_vals["lighting_power_allowance_p"] + space_lighting_power_per_area_p = calc_vals[ + "space_lighting_power_per_area_p" + ] + space_lighting_power_per_area_u = calc_vals[ + "space_lighting_power_per_area_u" + ] + + return std_equal( + space_lighting_power_per_area_p, + max(lighting_power_allowance_p, space_lighting_power_per_area_u), ) diff --git a/rct229/rulesets/ashrae9012019/section6/section6rule3.py b/rct229/rulesets/ashrae9012019/section6/section6rule3.py index d927b38f5..b1e481784 100644 --- a/rct229/rulesets/ashrae9012019/section6/section6rule3.py +++ b/rct229/rulesets/ashrae9012019/section6/section6rule3.py @@ -63,6 +63,12 @@ def __init__(self): rmds_used=produce_ruleset_model_description( USER=True, BASELINE_0=False, PROPOSED=True ), + precision={ + "total_space_lpd_p": { + "precision": 0.01, + "unit": "W/ft2", + } + }, ) def get_calc_vals(self, context, data=None): @@ -96,6 +102,6 @@ def manual_check_required(self, context, calc_vals=None, data=None): ) def rule_check(self, context, calc_vals=None, data=None): - total_space_lpd_u = calc_vals["total_space_lpd_u"] - total_space_lpd_p = calc_vals["total_space_lpd_p"] - return std_equal(total_space_lpd_u, total_space_lpd_p) + return self.precision_comparison["total_space_lpd_p"]( + calc_vals["total_space_lpd_p"], calc_vals["total_space_lpd_u"] + ) diff --git a/rct229/rulesets/ashrae9012019/section6/section6rule4.py b/rct229/rulesets/ashrae9012019/section6/section6rule4.py index 64e446cb7..d468c67ba 100644 --- a/rct229/rulesets/ashrae9012019/section6/section6rule4.py +++ b/rct229/rulesets/ashrae9012019/section6/section6rule4.py @@ -128,6 +128,34 @@ def rule_check(self, context, calc_vals=None, data=None): total_space_lpd_b = calc_vals["total_space_lpd_b"] lpd_allowance_b = calc_vals["lpd_allowance_b"] + return ( + # Not Case 1 + not ( + space_lighting_status_type_p + == LightingStatusType.AS_DESIGNED_OR_AS_EXISTING + and not lighting_space_type_b + ) + # Passes for both values of space_lighting_status_type_p + and ( + space_lighting_status_type_p + in [ + LightingStatusType.AS_DESIGNED_OR_AS_EXISTING, + LightingStatusType.NOT_YET_DESIGNED_OR_MATCH_TABLE_9_5_1, + ] + and total_space_lpd_b == lpd_allowance_b + ) + ) + + def is_tolerance_fail(self, context, calc_vals=None, data=None): + space_b = context.BASELINE_0 + lighting_space_type_b = space_b.get("lighting_space_type") + + space_lighting_status_type_p = calc_vals[ + "space_lighting_status_type_p" + ] + total_space_lpd_b = calc_vals["total_space_lpd_b"] + lpd_allowance_b = calc_vals["lpd_allowance_b"] + return ( # Not Case 1 not ( diff --git a/rct229/rulesets/ashrae9012019/section6/section6rule5.py b/rct229/rulesets/ashrae9012019/section6/section6rule5.py index 0b446a403..17d5406d5 100644 --- a/rct229/rulesets/ashrae9012019/section6/section6rule5.py +++ b/rct229/rulesets/ashrae9012019/section6/section6rule5.py @@ -185,7 +185,6 @@ def rule_check(self, context, calc_vals=None, data=None): schedule_comparison_result = calc_vals[ "schedule_comparison_result" ] - return ( schedule_comparison_result["total_hours_compared"] == schedule_comparison_result["total_hours_matched"] diff --git a/rct229/ruletest_engine/ruletest_jsons/ashrae9012019/section5/rule_5_15.json b/rct229/ruletest_engine/ruletest_jsons/ashrae9012019/section5/rule_5_15.json index ac0c1a5da..728f9123e 100644 --- a/rct229/ruletest_engine/ruletest_jsons/ashrae9012019/section5/rule_5_15.json +++ b/rct229/ruletest_engine/ruletest_jsons/ashrae9012019/section5/rule_5_15.json @@ -283,7 +283,7 @@ "id": "SubSurface 1", "classification": "WINDOW", "u_factor": 3.2366105565544463, - "glazed_area": 2.7870912, + "glazed_area": 5.5741824, "opaque_area": 7.432243199999999 } ], @@ -302,7 +302,7 @@ "id": "SubSurface 2", "classification": "WINDOW", "u_factor": 3.2366105565544463, - "glazed_area": 2.7870912, + "glazed_area": 5.5741824, "opaque_area": 7.432243199999999 } ],