Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 14 additions & 9 deletions docs/ashrae_90p1_2019/section6/Rule6-5.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
**Appendix G Section:** Section G3.1-6 Modeling Requirements for the Baseline building
**Appendix G Section Reference:** None

**Applicability:** All required data elements exist for B_RMR
**Applicability Checks:**

**Applicability:** All required data elements exist for B_RMD
**Applicability Checks:**
1. Building total area is more than 5,000sq.ft.

**Manual Check:** Yes
Expand All @@ -30,24 +29,30 @@
- **Applicability Check 1:**`if building_total_area_b > 5000:`

- For each space in building_b: `space_b in building_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)`

- Skip evaluating plenums, crawlspaces, and interstitial spaces that have no lighting power: `if total_space_LPD_b ==0 and space_b.function in [PLENUM, CRAWL_SPACE, INTERSTITIAL_SPACE]: continue`

- Get normalized space lighting schedule: `normalized_schedule_b = normalize_interior_lighting_schedules(space_b.interior_lighting, false)`

- Get matching space in P_RMR: `space_p = match_data_element(P_RMR, Spaces, space_b.id)`
- Get matching space in P_RMD: `space_p = match_data_element(P_RMD, Spaces, space_b.id)`

- Get normalized space lighting schedule in P_RMR: `normalized_schedule_p = normalize_interior_lighting_schedules(space_p.interior_lighting, false)`
- Get normalized space lighting schedule in P_RMD: `normalized_schedule_p = normalize_interior_lighting_schedules(space_p.interior_lighting, false)`

- Check if automatic shutoff control is modeled in space during building closed hours (i.e. if lighting schedule hourly value in B_RMR is equal to P_RMR during building closed hours): `schedule_comparison_result = compare_schedules(normalized_schedule_b, normalized_schedule_p, inverse(building_open_schedule_b))`
- Check if automatic shutoff control is modeled in space during building closed hours (i.e. if lighting schedule hourly value in B_RMD is equal to P_RMD during building closed hours): `schedule_comparison_result = compare_schedules(normalized_schedule_b, normalized_schedule_p, inverse(building_open_schedule_b))`

**Rule Assertion:**

- Case 1: For building closed hours, if lighting schedule hourly value in B_RMR is equal to P_RMR: `if schedule_comparison_result["total_hours_compared"] == schedule_comparison_result["total_hours_matched"]: PASS`
- 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: For building closed hours, if lighting schedule hourly value in B_RMD is equal to P_RMD: `if schedule_comparison_result["total_hours_compared"] == schedule_comparison_result["total_hours_matched"]: PASS`

- Case 2: Else: `else: Failed`
- Case 3: Else: `else: Failed`


**Notes:**
1. Updated the Rule ID from 6-9 to 6-6 on 6/3/2022
2. Updated the Rule ID from 6-6 to 6-5 on 6/8/2022
2. Updated the Rule ID from 6-6 to 6-5 on 6/8/2022
3. Updated to exclude crawl space, plenum or interstitial space on 9/29/2025.

**[Back](../_toc.md)**
52 changes: 52 additions & 0 deletions rct229/rulesets/ashrae9012019/section6/section6rule5.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,21 @@
from rct229.utils.jsonpath_utils import find_all, find_exactly_one_with_field_value
from rct229.utils.masks import invert_mask
from rct229.utils.pint_utils import ZERO
from rct229.schema.schema_enums import SchemaEnums

SpaceFunctionOptions = SchemaEnums.schema_enums["SpaceFunctionOptions"]

NA_SPACE_FUNCTIONS = [
SpaceFunctionOptions.PLENUM,
SpaceFunctionOptions.CRAWL_SPACE,
SpaceFunctionOptions.INTERSTITIAL_SPACE,
]
BUILDING_AREA_CUTTOFF = ureg("5000 ft2")
NA_SPACE_MSG = (
"Space is a crawl space, plenum, interstitial space, or an unoccupiable "
"space type with lighting power modeled. Unable to determine whether this "
"space should be included in the check."
)


class PRM9012019Rule08a45(RuleDefinitionListIndexedBase):
Expand Down Expand Up @@ -110,6 +123,27 @@ def create_data(self, context, data=None):
"avg_zone_height_p": get_avg_zone_height(zone_p),
}

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),
ZERO.POWER_PER_AREA,
)

space_function_b = space_b.get("function")
lighting_space_type_b = space_b.get("lighting_space_type")

is_na_or_none = (
space_function_b in NA_SPACE_FUNCTIONS
or lighting_space_type_b == "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(
Expand All @@ -119,6 +153,7 @@ def __init__(self):
rmds_used=produce_ruleset_model_description(
USER=False, BASELINE_0=True, PROPOSED=True
),
manual_check_required_msg=NA_SPACE_MSG,
)

def is_applicable(self, context, data=None):
Expand Down Expand Up @@ -176,6 +211,23 @@ def get_calc_vals(self, context, data=None):
"schedule_comparison_result": schedule_comparison_result
}

def manual_check_required(self, context, calc_vals=None, data=None):
space_b = context.BASELINE_0

total_space_lpd_b = sum(
find_all("$.interior_lighting[*].power_per_area", space_b),
ZERO.POWER_PER_AREA,
)

space_function_b = space_b.get("function")
lighting_space_type_b = space_b.get("lighting_space_type")

# NA or NONE space WITH lighting
return (
space_function_b in NA_SPACE_FUNCTIONS
or lighting_space_type_b == "NONE"
) and total_space_lpd_b > ZERO.POWER_PER_AREA

def rule_check(self, context, calc_vals=None, data=None):
schedule_comparison_result = calc_vals[
"schedule_comparison_result"
Expand Down
Loading