From a64d3ad87e3686429b33b89263526efe49bdb199 Mon Sep 17 00:00:00 2001 From: Christina LaPerle Date: Mon, 29 Sep 2025 09:10:08 -0400 Subject: [PATCH 1/6] Updated RDS to exclude plenums, interstitial, and crawl spaces. --- docs/section6/Rule6-4.md | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/docs/section6/Rule6-4.md b/docs/section6/Rule6-4.md index 9e8cb336d3..54b96faced 100644 --- a/docs/section6/Rule6-4.md +++ b/docs/section6/Rule6-4.md @@ -7,7 +7,7 @@ **Appendix G Section:** Section G3.1-6 Modeling Requirements for the Baseline **Applicability:** All required data elements exist for B_RMR -**Applicability Checks:** None +**Applicability Checks:** Space function is not crawl space, plenum or interstitial space. **Manual Check:** No **Evaluation Context:** Each Data Element @@ -21,43 +21,44 @@ ## Rule Logic: -- For each building segment in the baseline model: `building_segment_b in B_RMR.building.building_segments:` +- For each building segment in the baseline model: `building_segment_b in B_RMD.building.building_segments:` - - Get matching building segment in R_RMR: `building_segment_p = match_data_element(P_RMR, BuildingSegments, building_segment_b.id)` + - Get matching building segment in P_RMD: `building_segment_p = match_data_element(P_RMD, BuildingSegments, building_segment_b.id)` - - Get lighting status type dictionary for P_RMR: `space_lighting_status_type_dict_p = get_lighting_status_type(building_segment_p)` + - Get lighting status type dictionary for P_RMD: `space_lighting_status_type_dict_p = get_lighting_status_type(building_segment_p)` - For each thermal block in building segment: `thermal_block_b in building_segment_b.thermal_blocks:` - For each zone in thermal block: `zone_b in thermal_block_b.zones:` - For each space in zone: `space_b in zone_b.spaces:` + - **Applicability Check:** Check if the space is a crawl space, plenum or interstitial space: `if space_p.function in [PLENUM, CRAWL_SPACE, INTERSTITIAL_SPACE]:` + - Rule is not applicable because space function is crawl space, plenum or interstitial space: RULE_NOT_APPLICABLE: `continue` - - For each space in zone: `space_b in zone_b.spaces:` + - Get total lighting power density in space: `total_space_LPD_b = sum(interior_lighting.power_per_area for interior_lighting in space_b.interior_lighting)` - - Get total lighting power density in space: `total_space_LPD_b = sum(interior_lighting.power_per_area for interior_lighting in space_b.interior_lighting)` + - Get lighting status type for space: `space_lighting_status_type = space_lighting_status_type_dict_p[match_data_element(P_RMR, Spaces, space_b.id).id]` - - Get lighting status type for space: `space_lighting_status_type = space_lighting_status_type_dict_p[match_data_element(P_RMR, Spaces, space_b.id).id]` + - Check if lighting space type is specified, get lighting power density allowance from Table G3.7: `if space_b.lighting_space_type: LPD_allowance_b = data_lookup(table_G3_7, space_b.lighting_space_type)` - - Check if lighting space type is specified, get lighting power density allowance from Table G3.7: `if space_b.lighting_space_type: LPD_allowance_b = data_lookup(table_G3_7, space_b.lighting_space_type)` + - Else, lighting space type is not specified, assume "Office-Open Plan" as lighting space type to get lighting power density allowance from Table G3.7: `else: LPD_allowance_b = data_lookup(table_G3_7, "OFFICE-OPEN PLAN")` - - Else, lighting space type is not specified, assume "Office-Open Plan" as lighting space type to get lighting power density allowance from Table G3.7: `else: LPD_allowance_b = data_lookup(table_G3_7, "OFFICE-OPEN PLAN")` + **Rule Assertion:** - **Rule Assertion:** + - Case 1: If space lighting status type is as-designed or as-existing, and lighting space type is not specified: `if ( space_lighting_status_type == "AS-DESIGNED OR AS-EXISTING" ) AND ( NOT space_b.lighting_space_type ): FAIL and raise_warning "P_RMR LIGHTING STATUS TYPE IS AS-DESIGNED OR AS-EXISTING. BUT LIGHTING SPACE TYPE IN B_RMR IS NOT SPECIFIED."` - - Case 1: If space lighting status type is as-designed or as-existing, and lighting space type is not specified: `if ( space_lighting_status_type == "AS-DESIGNED OR AS-EXISTING" ) AND ( NOT space_b.lighting_space_type ): FAIL and raise_warning "P_RMR LIGHTING STATUS TYPE IS AS-DESIGNED OR AS-EXISTING. BUT LIGHTING SPACE TYPE IN B_RMR IS NOT SPECIFIED."` + - Case 2: Else if space lighting status type is as-designed or as-existing, and space total interior lighting power density in B_RMR matches Table G3.7: `else if ( space_lighting_status_type == "AS-DESIGNED OR AS-EXISTING" ) AND ( total_space_LPD_b == LPD_allowance_b ): PASS` - - Case 2: Else if space lighting status type is as-designed or as-existing, and space total interior lighting power density in B_RMR matches Table G3.7: `else if ( space_lighting_status_type == "AS-DESIGNED OR AS-EXISTING" ) AND ( total_space_LPD_b == LPD_allowance_b ): PASS` + - Case 3: Else if space lighting status type is as-designed or as-existing, and space total interior lighting power density in B_RMR does not match Table G3.7: `else if ( space_lighting_status_type == "AS-DESIGNED OR AS-EXISTING" ) AND ( total_space_LPD_b != LPD_allowance_b ): FAIL` - - Case 3: Else if space lighting status type is as-designed or as-existing, and space total interior lighting power density in B_RMR does not match Table G3.7: `else if ( space_lighting_status_type == "AS-DESIGNED OR AS-EXISTING" ) AND ( total_space_LPD_b != LPD_allowance_b ): FAIL` + - Case 4: Else if space lighting status type is not-yet designed or matches Table_9_5_1, and space total interior lighting power density in B_RMR matches Table G3.7: `else if ( space_lighting_status_type == "NOT-YET DESIGNED OR MATCH TABLE_9_5_1" ) AND ( total_space_LPD_b == LPD_allowance_b ): PASS` - - Case 4: Else if space lighting status type is not-yet designed or matches Table_9_5_1, and space total interior lighting power density in B_RMR matches Table G3.7: `else if ( space_lighting_status_type == "NOT-YET DESIGNED OR MATCH TABLE_9_5_1" ) AND ( total_space_LPD_b == LPD_allowance_b ): PASS` - - - Case 5: Else, space lighting status type is not-yet designed or matches Table_9_5_1, and space total interior lighting power density in B_RMR does not match Table G3.7: `else if ( space_lighting_status_type == "NOT-YET DESIGNED OR MATCH TABLE_9_5_1" ) AND ( total_space_LPD_b != LPD_allowance_b ): FAIL` + - Case 5: Else, space lighting status type is not-yet designed or matches Table_9_5_1, and space total interior lighting power density in B_RMR does not match Table G3.7: `else if ( space_lighting_status_type == "NOT-YET DESIGNED OR MATCH TABLE_9_5_1" ) AND ( total_space_LPD_b != LPD_allowance_b ): FAIL` **Notes:** 1. Requirements from addendum AF to 90.1-2019 have not been incorporated into this RDS. 2. Updated the Rule ID from 6-7 to 6-5 on 6/3/2022 3. Update the Rule ID from 6-5 to 6-4 on 6/8/2022 + 4. Updated on 9/29/2025 to exclude crawl space, plenum or interstitial space **[Back](../_toc.md)** From d2832e1706c9facf085c0259200066f7bedaec10 Mon Sep 17 00:00:00 2001 From: Jackson Jarboe <122476654+JacksonJ-KC@users.noreply.github.com> Date: Tue, 18 Nov 2025 09:26:50 -0500 Subject: [PATCH 2/6] plenum, crawlspace, interstitial updates --- docs/section6/Rule6-4.md | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/docs/section6/Rule6-4.md b/docs/section6/Rule6-4.md index 54b96faced..7464fb3966 100644 --- a/docs/section6/Rule6-4.md +++ b/docs/section6/Rule6-4.md @@ -6,9 +6,9 @@ **Appendix G Section:** Section G3.1-6 Modeling Requirements for the Baseline -**Applicability:** All required data elements exist for B_RMR -**Applicability Checks:** Space function is not crawl space, plenum or interstitial space. -**Manual Check:** No +**Applicability:** All required data elements exist for B_RMD +**Applicability Checks:** None +**Manual Check:** No **Evaluation Context:** Each Data Element **Data Lookup:** Table G3.7 @@ -23,7 +23,7 @@ - For each building segment in the baseline model: `building_segment_b in B_RMD.building.building_segments:` - - Get matching building segment in P_RMD: `building_segment_p = match_data_element(P_RMD, BuildingSegments, building_segment_b.id)` + - Get matching building segment in R_RMD: `building_segment_p = match_data_element(P_RMD, BuildingSegments, building_segment_b.id)` - Get lighting status type dictionary for P_RMD: `space_lighting_status_type_dict_p = get_lighting_status_type(building_segment_p)` @@ -32,33 +32,37 @@ - For each zone in thermal block: `zone_b in thermal_block_b.zones:` - For each space in zone: `space_b in zone_b.spaces:` - - **Applicability Check:** Check if the space is a crawl space, plenum or interstitial space: `if space_p.function in [PLENUM, CRAWL_SPACE, INTERSTITIAL_SPACE]:` - - Rule is not applicable because space function is crawl space, plenum or interstitial space: RULE_NOT_APPLICABLE: `continue` - - Get total lighting power density in space: `total_space_LPD_b = sum(interior_lighting.power_per_area for interior_lighting in space_b.interior_lighting)` + - For each space in zone: `space_b in zone_b.spaces:` - - Get lighting status type for space: `space_lighting_status_type = space_lighting_status_type_dict_p[match_data_element(P_RMR, Spaces, space_b.id).id]` + - Get total lighting power density in space: `total_space_LPD_b = sum(interior_lighting.power_per_area for interior_lighting in space_b.interior_lighting)` + + - Get the space function to later check if the space is crawl space, interstitial space, or plenum: `space_function_b = space_b.function` + + - Skip evaluation for any spaces that are plenums, crawl spaces, or interstitial spaces and have no lighting power modeled: `if ( total_space_LPD_b == 0 ) AND ( space_function_b in [CRAWL_SPACE, INTERSTITIAL_SPACE, PLENUM] ): continue` - - Check if lighting space type is specified, get lighting power density allowance from Table G3.7: `if space_b.lighting_space_type: LPD_allowance_b = data_lookup(table_G3_7, space_b.lighting_space_type)` + - Get lighting status type for space: `space_lighting_status_type = space_lighting_status_type_dict_p[match_data_element(P_RMD, Spaces, space_b.id).id]` - - Else, lighting space type is not specified, assume "Office-Open Plan" as lighting space type to get lighting power density allowance from Table G3.7: `else: LPD_allowance_b = data_lookup(table_G3_7, "OFFICE-OPEN PLAN")` + - Check if lighting space type is specified, get lighting power density allowance from Table G3.7: `if space_b.lighting_space_type: LPD_allowance_b = data_lookup(table_G3_7, space_b.lighting_space_type)` - **Rule Assertion:** + - Else, lighting space type is not specified, assume "Office-Open Plan" as lighting space type to get lighting power density allowance from Table G3.7: `else: LPD_allowance_b = data_lookup(table_G3_7, "OFFICE-OPEN PLAN")` - - Case 1: If space lighting status type is as-designed or as-existing, and lighting space type is not specified: `if ( space_lighting_status_type == "AS-DESIGNED OR AS-EXISTING" ) AND ( NOT space_b.lighting_space_type ): FAIL and raise_warning "P_RMR LIGHTING STATUS TYPE IS AS-DESIGNED OR AS-EXISTING. BUT LIGHTING SPACE TYPE IN B_RMR IS NOT SPECIFIED."` + **Rule Assertion:** + - Case 1: If space has lighting power and is crawl space, interstitial space, or plenum: UNDETERMINED `if ( total_space_LPD_b > 0 ) AND ( space_function_b in [CRAWL_SPACE, INTERSTITIAL_SPACE, PLENUM] ): UNDETERMINED and raise_warning f"Space function is {space_function_b} and has lighting power modeled. Unable to determine whether this space should be included in the check."` - - Case 2: Else if space lighting status type is as-designed or as-existing, and space total interior lighting power density in B_RMR matches Table G3.7: `else if ( space_lighting_status_type == "AS-DESIGNED OR AS-EXISTING" ) AND ( total_space_LPD_b == LPD_allowance_b ): PASS` + - Case 1: If space lighting status type is as-designed or as-existing, and lighting space type is not specified: FAIL `if ( space_lighting_status_type == "AS-DESIGNED OR AS-EXISTING" ) AND ( NOT space_b.lighting_space_type ): FAIL and raise_warning "The proposed lighting status is 'AS-DESIGNED OR AS-EXISTING' but the baseline lighting space type was not specified."` - - Case 3: Else if space lighting status type is as-designed or as-existing, and space total interior lighting power density in B_RMR does not match Table G3.7: `else if ( space_lighting_status_type == "AS-DESIGNED OR AS-EXISTING" ) AND ( total_space_LPD_b != LPD_allowance_b ): FAIL` + - Case 2: Else if space lighting status type is as-designed or as-existing, and space total interior lighting power density in B_RMD matches Table G3.7: PASS `else if ( space_lighting_status_type == "AS-DESIGNED OR AS-EXISTING" ) AND ( total_space_LPD_b == LPD_allowance_b ): PASS` - - Case 4: Else if space lighting status type is not-yet designed or matches Table_9_5_1, and space total interior lighting power density in B_RMR matches Table G3.7: `else if ( space_lighting_status_type == "NOT-YET DESIGNED OR MATCH TABLE_9_5_1" ) AND ( total_space_LPD_b == LPD_allowance_b ): PASS` + - Case 3: Else if space lighting status type is as-designed or as-existing, and space total interior lighting power density in B_RMD does not match Table G3.7: FAIL `else if ( space_lighting_status_type == "AS-DESIGNED OR AS-EXISTING" ) AND ( total_space_LPD_b != LPD_allowance_b ): FAIL` - - Case 5: Else, space lighting status type is not-yet designed or matches Table_9_5_1, and space total interior lighting power density in B_RMR does not match Table G3.7: `else if ( space_lighting_status_type == "NOT-YET DESIGNED OR MATCH TABLE_9_5_1" ) AND ( total_space_LPD_b != LPD_allowance_b ): FAIL` + - Case 4: Else if space lighting status type is not-yet designed or matches Table_9_5_1, and space total interior lighting power density in B_RMD matches Table G3.7: PASS `else if ( space_lighting_status_type == "NOT-YET DESIGNED OR MATCH TABLE_9_5_1" ) AND ( total_space_LPD_b == LPD_allowance_b ): PASS` + + - Case 5: Else, space lighting status type is not-yet designed or matches Table_9_5_1, and space total interior lighting power density in B_RMD does not match Table G3.7: FAIL `else if ( space_lighting_status_type == "NOT-YET DESIGNED OR MATCH TABLE_9_5_1" ) AND ( total_space_LPD_b != LPD_allowance_b ): FAIL` **Notes:** 1. Requirements from addendum AF to 90.1-2019 have not been incorporated into this RDS. 2. Updated the Rule ID from 6-7 to 6-5 on 6/3/2022 3. Update the Rule ID from 6-5 to 6-4 on 6/8/2022 - 4. Updated on 9/29/2025 to exclude crawl space, plenum or interstitial space **[Back](../_toc.md)** From 0d933a8a4843698c121d1eba04b8a346c6ba4149 Mon Sep 17 00:00:00 2001 From: Jackson Jarboe <122476654+JacksonJ-KC@users.noreply.github.com> Date: Wed, 19 Nov 2025 11:59:18 -0500 Subject: [PATCH 3/6] update per CML review comments --- docs/section6/Rule6-4.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/section6/Rule6-4.md b/docs/section6/Rule6-4.md index 7464fb3966..329d1c2084 100644 --- a/docs/section6/Rule6-4.md +++ b/docs/section6/Rule6-4.md @@ -50,15 +50,15 @@ **Rule Assertion:** - Case 1: If space has lighting power and is crawl space, interstitial space, or plenum: UNDETERMINED `if ( total_space_LPD_b > 0 ) AND ( space_function_b in [CRAWL_SPACE, INTERSTITIAL_SPACE, PLENUM] ): UNDETERMINED and raise_warning f"Space function is {space_function_b} and has lighting power modeled. Unable to determine whether this space should be included in the check."` - - Case 1: If space lighting status type is as-designed or as-existing, and lighting space type is not specified: FAIL `if ( space_lighting_status_type == "AS-DESIGNED OR AS-EXISTING" ) AND ( NOT space_b.lighting_space_type ): FAIL and raise_warning "The proposed lighting status is 'AS-DESIGNED OR AS-EXISTING' but the baseline lighting space type was not specified."` + - Case 2: Else if space lighting status type is as-designed or as-existing, and lighting space type is not specified: UNDETERMINED ` else if ( space_lighting_status_type == "AS-DESIGNED OR AS-EXISTING" ) AND ( NOT space_b.lighting_space_type ): UNDETERMINED and raise_warning "The proposed lighting status is 'AS-DESIGNED OR AS-EXISTING' but the baseline lighting space type was not specified."` - - Case 2: Else if space lighting status type is as-designed or as-existing, and space total interior lighting power density in B_RMD matches Table G3.7: PASS `else if ( space_lighting_status_type == "AS-DESIGNED OR AS-EXISTING" ) AND ( total_space_LPD_b == LPD_allowance_b ): PASS` + - Case 3: Else if space lighting status type is as-designed or as-existing, and space total interior lighting power density in B_RMD matches Table G3.7: PASS `else if ( space_lighting_status_type == "AS-DESIGNED OR AS-EXISTING" ) AND ( total_space_LPD_b == LPD_allowance_b ): PASS` - - Case 3: Else if space lighting status type is as-designed or as-existing, and space total interior lighting power density in B_RMD does not match Table G3.7: FAIL `else if ( space_lighting_status_type == "AS-DESIGNED OR AS-EXISTING" ) AND ( total_space_LPD_b != LPD_allowance_b ): FAIL` + - Case 4: Else if space lighting status type is as-designed or as-existing, and space total interior lighting power density in B_RMD does not match Table G3.7: FAIL `else if ( space_lighting_status_type == "AS-DESIGNED OR AS-EXISTING" ) AND ( total_space_LPD_b != LPD_allowance_b ): FAIL` - - Case 4: Else if space lighting status type is not-yet designed or matches Table_9_5_1, and space total interior lighting power density in B_RMD matches Table G3.7: PASS `else if ( space_lighting_status_type == "NOT-YET DESIGNED OR MATCH TABLE_9_5_1" ) AND ( total_space_LPD_b == LPD_allowance_b ): PASS` + - Case 5: Else if space lighting status type is not-yet designed or matches Table_9_5_1, and space total interior lighting power density in B_RMD matches Table G3.7: PASS `else if ( space_lighting_status_type == "NOT-YET DESIGNED OR MATCH TABLE_9_5_1" ) AND ( total_space_LPD_b == LPD_allowance_b ): PASS` - - Case 5: Else, space lighting status type is not-yet designed or matches Table_9_5_1, and space total interior lighting power density in B_RMD does not match Table G3.7: FAIL `else if ( space_lighting_status_type == "NOT-YET DESIGNED OR MATCH TABLE_9_5_1" ) AND ( total_space_LPD_b != LPD_allowance_b ): FAIL` + - Case 6: Else, space lighting status type is not-yet designed or matches Table_9_5_1, and space total interior lighting power density in B_RMD does not match Table G3.7: FAIL `else if ( space_lighting_status_type == "NOT-YET DESIGNED OR MATCH TABLE_9_5_1" ) AND ( total_space_LPD_b != LPD_allowance_b ): FAIL` **Notes:** 1. Requirements from addendum AF to 90.1-2019 have not been incorporated into this RDS. From b7d274db15d29f223cedcf54af01b1a1b5b4c1f8 Mon Sep 17 00:00:00 2001 From: Jackson Jarboe <122476654+JacksonJ-KC@users.noreply.github.com> Date: Tue, 23 Dec 2025 15:46:17 -0500 Subject: [PATCH 4/6] handle plenum, interstitial, crawl, NONE --- .../ashrae9012019/section6/section6rule4.py | 162 ++++++++++++------ 1 file changed, 112 insertions(+), 50 deletions(-) diff --git a/rct229/rulesets/ashrae9012019/section6/section6rule4.py b/rct229/rulesets/ashrae9012019/section6/section6rule4.py index 86e6913e97..3219dd8eef 100644 --- a/rct229/rulesets/ashrae9012019/section6/section6rule4.py +++ b/rct229/rulesets/ashrae9012019/section6/section6rule4.py @@ -19,7 +19,14 @@ OFFICE_OPEN_PLAN = SchemaEnums.schema_enums[ "LightingSpaceOptions2019ASHRAE901TG37" ].OFFICE_OPEN_PLAN -FAIL_MSG = "P_RMD lighting status type is as-designed or as-existing. But lighting space type in B_RMD is not specified." +CASE1_MSG = "The baseline model included at least one plenum, crawlspace, or interstitial space with lighting power. Unable to determine whether these spaces should be included in the check." +CASE2_MSG = "Proposed lighting status type is as-designed or as-existing, but the baseline lighting space type is not specified." +SpaceFunctionOptions = SchemaEnums.schema_enums["SpaceFunctionOptions"] +NA_SPACE_FUNCTIONS = [ + SpaceFunctionOptions.PLENUM, + SpaceFunctionOptions.CRAWL_SPACE, + SpaceFunctionOptions.INTERSTITIAL_SPACE, +] class PRM9012019Rule22l93(RuleDefinitionListIndexedBase): @@ -74,15 +81,28 @@ def __init__(self): def create_data(self, context, data=None): zone_b = context.BASELINE_0 - # We will need this after Weili's update to table_G3_7_lookup() return {"avg_zone_ht_b": get_avg_zone_height(zone_b)} + def list_filter(self, context_item, data): + space_b = context_item.BASELINE_0 + total_space_lpd_b = sum( + find_all("$.interior_lighting[*].power_per_area", space_b), + start=ZERO.POWER_PER_AREA, + ) + + is_na_or_none = ( + space_b.get("function") in NA_SPACE_FUNCTIONS + or space_b.get("lighting_space_type") == "NONE" + ) + + # Exclude only NA or NONE spaces with zero lighting + return not (is_na_or_none and total_space_lpd_b == ZERO.POWER_PER_AREA) + class SpaceRule(RuleDefinitionBase): def __init__(self): super( PRM9012019Rule22l93.BuildingSegmentRule.ZoneRule.SpaceRule, self ).__init__( - fail_msg=FAIL_MSG, rmds_used=produce_ruleset_model_description( USER=False, BASELINE_0=True, PROPOSED=True ), @@ -101,34 +121,94 @@ def get_calc_vals(self, context, data=None): find_all("$.interior_lighting[*].power_per_area", space_b), start=ZERO.POWER_PER_AREA, ) + space_function_b = space_b.get("function") + lighting_space_type_b = space_b.get("lighting_space_type") + space_lighting_status_type_p = data[ "building_segment_lighting_status_type_dict_p" ][space_p["id"]] - lpd_allowance_b = ( - table_G3_7_lookup( - space_b["lighting_space_type"], + + # Determine LPD allowance + if lighting_space_type_b is not None: + lpd_allowance_b = table_G3_7_lookup( + lighting_space_type_b, data["avg_zone_ht_b"], getattr_(space_b, "Space", "floor_area"), - ) - if "lighting_space_type" in space_b - else table_G3_7_lookup( + )["lpd"] + else: + lpd_allowance_b = table_G3_7_lookup( OFFICE_OPEN_PLAN, data["avg_zone_ht_b"], getattr_(space_b, "Space", "floor_area"), - ) - )["lpd"] + )["lpd"] return { - "lighting_space_type_b": space_b.get("lighting_space_type"), + "space_function_b": space_function_b, + "lighting_space_type_b": lighting_space_type_b, "total_space_lpd_b": CalcQ("power_density", total_space_lpd_b), "space_lighting_status_type_p": space_lighting_status_type_p, - "lpd_allowance_b": CalcQ("power_density", lpd_allowance_b), + "lpd_allowance_b": ( + CalcQ("power_density", lpd_allowance_b) + if lpd_allowance_b is not None + else None + ), } - def rule_check(self, context, calc_vals=None, data=None): - space_b = context.BASELINE_0 - lighting_space_type_b = space_b.get("lighting_space_type") + def manual_check_required(self, context, calc_vals=None, data=None): + space_function_b = calc_vals["space_function_b"] + lighting_space_type_b = calc_vals["lighting_space_type_b"] + space_lighting_status_type_p = calc_vals[ + "space_lighting_status_type_p" + ] + total_space_lpd_b = calc_vals["total_space_lpd_b"] + + # Case 1: NA space with lighting + if ( + space_function_b in NA_SPACE_FUNCTIONS + and total_space_lpd_b > ZERO.POWER_PER_AREA + ): + return True + + # Case 2: as-designed / as-existing but lighting space type missing + if ( + space_lighting_status_type_p + == LightingStatusType.AS_DESIGNED_OR_AS_EXISTING + and lighting_space_type_b is None + ): + return True + + return False + + def get_manual_check_required_msg( + self, context, calc_vals=None, data=None + ): + space_function_b = calc_vals["space_function_b"] + lighting_space_type_b = calc_vals["lighting_space_type_b"] + space_lighting_status_type_p = calc_vals[ + "space_lighting_status_type_p" + ] + total_space_lpd_b = calc_vals["total_space_lpd_b"] + + # Case 1: NA space with lighting + if ( + space_function_b in NA_SPACE_FUNCTIONS + and total_space_lpd_b > ZERO.POWER_PER_AREA + ): + return CASE1_MSG + + # Case 2: as-designed/as-existing but baseline lighting space type missing + if ( + space_lighting_status_type_p + == LightingStatusType.AS_DESIGNED_OR_AS_EXISTING + and lighting_space_type_b is None + ): + return CASE2_MSG + + return "" + def rule_check(self, context, calc_vals=None, data=None): + space_function_b = calc_vals["space_function_b"] + lighting_space_type_b = calc_vals["lighting_space_type_b"] space_lighting_status_type_p = calc_vals[ "space_lighting_status_type_p" ] @@ -136,7 +216,7 @@ def rule_check(self, context, calc_vals=None, data=None): lpd_allowance_b = calc_vals["lpd_allowance_b"] return ( - # Not Case 1 + # Not Case 2 not ( space_lighting_status_type_p == LightingStatusType.AS_DESIGNED_OR_AS_EXISTING @@ -156,45 +236,27 @@ def rule_check(self, context, calc_vals=None, data=None): ) 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_function_b = calc_vals["space_function_b"] + lighting_space_type_b = calc_vals["lighting_space_type_b"] 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 ( - 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 std_equal(lpd_allowance_b, total_space_lpd_b) - ) - ) + if ( + space_function_b in NA_SPACE_FUNCTIONS + and total_space_lpd_b > ZERO.POWER_PER_AREA + ): + return False - def get_fail_msg(self, context, calc_vals=None, data=None): - space_b = context.BASELINE_0 - lighting_space_type_b = space_b.get("lighting_space_type") + if lighting_space_type_b == "NONE": + return False - space_lighting_status_type_p = calc_vals[ - "space_lighting_status_type_p" - ] + if space_lighting_status_type_p in [ + LightingStatusType.AS_DESIGNED_OR_AS_EXISTING, + LightingStatusType.NOT_YET_DESIGNED_OR_MATCH_TABLE_9_5_1, + ]: + return std_equal(lpd_allowance_b, total_space_lpd_b) - return ( - "P_RMD lighting status type is as-designed or as-existing. But lighting space type in B_RMD is not specified." - if space_lighting_status_type_p - == LightingStatusType.AS_DESIGNED_OR_AS_EXISTING - and not lighting_space_type_b - else "" - ) + return False From 85f01c9ce57213b805edb7f67a69228104c135f9 Mon Sep 17 00:00:00 2001 From: Jackson Jarboe <122476654+JacksonJ-KC@users.noreply.github.com> Date: Tue, 23 Dec 2025 15:59:22 -0500 Subject: [PATCH 5/6] add schema enum --- .../ashrae_90_1_prm_2019.prm_interior_lighting.json | 13 +++++++++++++ .../ashrae9012019/data_fns/table_9_6_1_fns_test.py | 1 + .../ashrae9012019/data_fns/table_G3_7_fns.py | 1 + rct229/schema/Enumerations2019ASHRAE901.schema.json | 9 ++++++--- 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/rct229/rulesets/ashrae9012019/data/ashrae_90_1_prm_2019.prm_interior_lighting.json b/rct229/rulesets/ashrae9012019/data/ashrae_90_1_prm_2019.prm_interior_lighting.json index ac03f7bf21..ad4a0e37c1 100644 --- a/rct229/rulesets/ashrae9012019/data/ashrae_90_1_prm_2019.prm_interior_lighting.json +++ b/rct229/rulesets/ashrae9012019/data/ashrae_90_1_prm_2019.prm_interior_lighting.json @@ -1832,6 +1832,19 @@ "occup_sensor_auto_on_svgs": 0.1, "occup_sensor_savings": 0.125, "notes": null + }, + { + "template": "90.1-PRM-2019", + "lpd_space_type": "none", + "primary_space_type": "none", + "secondary_space_type": "none", + "w/ft^2": 0, + "w/ft": null, + "isresidential": 0, + "manon_or_partauto": 0, + "occup_sensor_auto_on_svgs": 0, + "occup_sensor_savings": 0, + "notes": null } ] } diff --git a/rct229/rulesets/ashrae9012019/data_fns/table_9_6_1_fns_test.py b/rct229/rulesets/ashrae9012019/data_fns/table_9_6_1_fns_test.py index 915ae7eb7e..6d7870b155 100644 --- a/rct229/rulesets/ashrae9012019/data_fns/table_9_6_1_fns_test.py +++ b/rct229/rulesets/ashrae9012019/data_fns/table_9_6_1_fns_test.py @@ -133,5 +133,6 @@ def test__building_type_enumeration_to_lpd_map(): "TRANSPORTATION_FACILITY_TICKET_COUNTER", "WAREHOUSE_STORAGE_AREA_MEDIUM_TO_BULKY_PALLETIZED_ITEMS", "WAREHOUSE_STORAGE_AREA_SMALLER_HAND_CARRIED_ITEMS", + "NONE", ], ) diff --git a/rct229/rulesets/ashrae9012019/data_fns/table_G3_7_fns.py b/rct229/rulesets/ashrae9012019/data_fns/table_G3_7_fns.py index 09064ada10..e724ddc209 100644 --- a/rct229/rulesets/ashrae9012019/data_fns/table_G3_7_fns.py +++ b/rct229/rulesets/ashrae9012019/data_fns/table_G3_7_fns.py @@ -112,6 +112,7 @@ "TRANSPORTATION_FACILITY_TICKET_COUNTER": "transportation ticket counter", "WAREHOUSE_STORAGE_AREA_MEDIUM_TO_BULKY_PALLETIZED_ITEMS": "warehouse - bulk storage", "WAREHOUSE_STORAGE_AREA_SMALLER_HAND_CARRIED_ITEMS": "warehouse - fine storage", + "NONE": "none", } FULL_AUTO_ON = SchemaEnums.schema_enums["LightingOccupancyControlOptions"].FULL_AUTO_ON diff --git a/rct229/schema/Enumerations2019ASHRAE901.schema.json b/rct229/schema/Enumerations2019ASHRAE901.schema.json index 119e5fe2e3..d0e69d8e76 100644 --- a/rct229/schema/Enumerations2019ASHRAE901.schema.json +++ b/rct229/schema/Enumerations2019ASHRAE901.schema.json @@ -257,7 +257,8 @@ "TRANSPORTATION_FACILITY_AIRPORT_CONCOURSE", "TRANSPORTATION_FACILITY_TICKET_COUNTER", "WAREHOUSE_STORAGE_AREA_MEDIUM_TO_BULKY_PALLETIZED_ITEMS", - "WAREHOUSE_STORAGE_AREA_SMALLER_HAND_CARRIED_ITEMS" + "WAREHOUSE_STORAGE_AREA_SMALLER_HAND_CARRIED_ITEMS", + "NONE" ], "descriptions": [ "Atrium - Low/Medium", @@ -362,7 +363,8 @@ "Transportation Facility - Airport concourse", "Transportation Facility - Ticket counter", "Warehouse \u00e2\u20ac\u201d Storage Area - Medium to bulky, palletized items", - "Warehouse \u00e2\u20ac\u201d Storage Area - Smaller, hand-carried items" + "Warehouse \u00e2\u20ac\u201d Storage Area - Smaller, hand-carried items", + "None" ], "notes": [ null, @@ -467,7 +469,8 @@ null, null, null, - null + null, + "Indicates that the space will have no occupancy, such as an elevator shaft." ] }, "LightingPurposeOptions2019ASHRAE901": { From 799ceb102cfbcf60b6ac2805529f7092def2206f Mon Sep 17 00:00:00 2001 From: jugonzal07 Date: Tue, 13 Jan 2026 11:41:27 -0500 Subject: [PATCH 6/6] Updated ruletest 6-4 to account for new plenum considerations and fixed 6-4's case 6 to ensure the lighting system is not-yet-designed by making the proposed system LPD equal to table 9.5.1's requirement. --- .../ashrae9012019/LTG/rule_6_4.json | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/rct229/ruletest_engine/ruletest_jsons/ashrae9012019/LTG/rule_6_4.json b/rct229/ruletest_engine/ruletest_jsons/ashrae9012019/LTG/rule_6_4.json index a304e57ac9..cf87de8fa1 100644 --- a/rct229/ruletest_engine/ruletest_jsons/ashrae9012019/LTG/rule_6_4.json +++ b/rct229/ruletest_engine/ruletest_jsons/ashrae9012019/LTG/rule_6_4.json @@ -3,10 +3,8 @@ "Section": 6, "Rule": 4, "Test": "a", - "test_description": "Project has one building segment with one zone and one space. The lighting system is as-designed or as-existing but the lighting space type has not been specified in the baseline ruleset project description. The lighting power density in the baseline ruleset project description cannot be verified.", - "expected_rule_outcome": "fail", - "expected_raised_message_includes": "P_RMD lighting status type is as-designed or as-existing. But lighting space type in B_RMD is not specified.", "standard": { + "ruleset": "ashrae9012019", "rule_id": "6-4", "ruleset_reference": "Table G3.1(6) Baseline Building Performance", "rule_description": "Where a complete lighting system exists and where a lighting system has been designed and submitted with design documents, the baseline LPD is equal to expected value in Standard 90.1-2019 Table G3.7. Where lighting neither exists nor is submitted with design documents, baseline LPD shall be determined in accordance with Table G3-7 for \"Office-Open Plan\" space type.", @@ -17,6 +15,9 @@ "mandatory_rule": "Full", "schema_version": "0.1.7" }, + "test_description": "Project has one building segment with one zone and one space. The lighting system is as-designed or as-existing but the lighting space type has not been specified in the baseline ruleset project description. The lighting power density in the baseline ruleset project description cannot be verified.", + "expected_rule_outcome": "undetermined", + "expected_raised_message_includes": "Proposed lighting status type is as-designed or as-existing, but the baseline lighting space type is not specified.", "rmd_transformations": { "proposed": { "id": "ASHRAE229 1", @@ -103,9 +104,8 @@ "Section": 6, "Rule": 4, "Test": "b", - "test_description": "Project has one building segment with one zone and one space. The lighting system is as-designed or as-existing and the lighting space type has been specified in the baseline ruleset project description. The lighting power density in the baseline ruleset project description is equal to the value specified in Standard 90.1-2019 Table G3.7 for the specified lighting space type.", - "expected_rule_outcome": "pass", "standard": { + "ruleset": "ashrae9012019", "rule_id": "6-4", "ruleset_reference": "Table G3.1(6) Baseline Building Performance", "rule_description": "Where a complete lighting system exists and where a lighting system has been designed and submitted with design documents, the baseline LPD is equal to expected value in Standard 90.1-2019 Table G3.7. Where lighting neither exists nor is submitted with design documents, baseline LPD shall be determined in accordance with Table G3-7 for \"Office-Open Plan\" space type.", @@ -116,6 +116,8 @@ "mandatory_rule": "Full", "schema_version": "0.1.7" }, + "test_description": "Project has one building segment with one zone and one space. The lighting system is as-designed or as-existing and the lighting space type has been specified in the baseline ruleset project description. The lighting power density in the baseline ruleset project description is equal to the value specified in Standard 90.1-2019 Table G3.7 for the specified lighting space type.", + "expected_rule_outcome": "pass", "rmd_transformations": { "proposed": { "id": "ASHRAE229 1", @@ -203,9 +205,8 @@ "Section": 6, "Rule": 4, "Test": "c", - "test_description": "Project has one building segment with one zone and one space. The lighting system is as-designed or as-existing and the lighting space type has been specified in the baseline ruleset project description. The lighting power density in the baseline ruleset project description is not equal to the value specified in Standard 90.1-2019 Table G3.7 for the specified lighting space type.", - "expected_rule_outcome": "fail", "standard": { + "ruleset": "ashrae9012019", "rule_id": "6-4", "ruleset_reference": "Table G3.1(6) Baseline Building Performance", "rule_description": "Where a complete lighting system exists and where a lighting system has been designed and submitted with design documents, the baseline LPD is equal to expected value in Standard 90.1-2019 Table G3.7. Where lighting neither exists nor is submitted with design documents, baseline LPD shall be determined in accordance with Table G3-7 for \"Office-Open Plan\" space type.", @@ -216,6 +217,8 @@ "mandatory_rule": "Full", "schema_version": "0.1.7" }, + "test_description": "Project has one building segment with one zone and one space. The lighting system is as-designed or as-existing and the lighting space type has been specified in the baseline ruleset project description. The lighting power density in the baseline ruleset project description is not equal to the value specified in Standard 90.1-2019 Table G3.7 for the specified lighting space type.", + "expected_rule_outcome": "fail", "rmd_transformations": { "proposed": { "id": "ASHRAE229 1", @@ -303,9 +306,8 @@ "Section": 6, "Rule": 4, "Test": "d", - "test_description": "Project has one building segment with one zone and one space. The lighting system is not-yet-designed and the lighting space type has not been specified in the baseline ruleset project description. The lighting power density in the baseline ruleset project description is equal to the value specified in Standard 90.1-2019 Table G3.7 for the lighting systems not-yet-designed.", - "expected_rule_outcome": "pass", "standard": { + "ruleset": "ashrae9012019", "rule_id": "6-4", "ruleset_reference": "Table G3.1(6) Baseline Building Performance", "rule_description": "Where a complete lighting system exists and where a lighting system has been designed and submitted with design documents, the baseline LPD is equal to expected value in Standard 90.1-2019 Table G3.7. Where lighting neither exists nor is submitted with design documents, baseline LPD shall be determined in accordance with Table G3-7 for \"Office-Open Plan\" space type.", @@ -316,6 +318,8 @@ "mandatory_rule": "Full", "schema_version": "0.1.7" }, + "test_description": "Project has one building segment with one zone and one space. The lighting system is not-yet-designed and the lighting space type has not been specified in the baseline ruleset project description. The lighting power density in the baseline ruleset project description is equal to the value specified in Standard 90.1-2019 Table G3.7 for the lighting systems not-yet-designed.", + "expected_rule_outcome": "pass", "rmd_transformations": { "proposed": { "id": "ASHRAE229 1", @@ -401,10 +405,8 @@ "Section": 6, "Rule": 4, "Test": "e", - "test_description": "Project has one building segment with one zone and one space. The lighting system is not-yet-designed and the lighting space type has not been specified in the baseline ruleset project description. The lighting power density in the baseline ruleset project description is not equal to the value specified in Standard 90.1-2019 Table G3.7 for the lighting systems not-yet-designed.", - "expected_rule_outcome": "fail", - "expected_raised_message_includes": "P_RMD lighting status type is as-designed or as-existing. But lighting space type in B_RMD is not specified.", "standard": { + "ruleset": "ashrae9012019", "rule_id": "6-4", "ruleset_reference": "Table G3.1(6) Baseline Building Performance", "rule_description": "Where a complete lighting system exists and where a lighting system has been designed and submitted with design documents, the baseline LPD is equal to expected value in Standard 90.1-2019 Table G3.7. Where lighting neither exists nor is submitted with design documents, baseline LPD shall be determined in accordance with Table G3-7 for \"Office-Open Plan\" space type.", @@ -415,6 +417,8 @@ "mandatory_rule": "Full", "schema_version": "0.1.7" }, + "test_description": "Project has one building segment with one zone and one space. The lighting system is not-yet-designed and the lighting space type has not been specified in the baseline ruleset project description. The lighting power density in the baseline ruleset project description is not equal to the value specified in Standard 90.1-2019 Table G3.7 for the lighting systems not-yet-designed.", + "expected_rule_outcome": "fail", "rmd_transformations": { "proposed": { "id": "ASHRAE229 1", @@ -439,7 +443,7 @@ { "id": "Space 1 Lighting 1", "occupancy_control_type": "NONE", - "power_per_area": 4.843759687519376 + "power_per_area": 6.888902666694223 } ] }