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
31 changes: 20 additions & 11 deletions docs/ashrae_90p1_2019/section6/Rule6-7.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@

# Lighting - Rule 6-7

**Rule ID:** 6-7
**Rule Description:** Proposed building is modeled with daylighting controls directly or through schedule adjustments.
**Appendix G Section:** Section 6 Lighting
**Appendix G Section Reference:** Section G3.1-6(h) Lighting: Modeling Requirements for the Proposed design
**Appendix G Section Reference:** Section G3.1-6(h) Lighting: Modeling Requirements for the Proposed design, Table 9.6.1 Minimum Control Requirements

**Applicability:** All required data elements exist for P_RMR
**Applicability:** All required data elements exist for P_RMD
**Applicability Checks:** None
**Manual Check:** Yes
**Evaluation Context:** Each Data Element
**Data Lookup:** None
## Rule Logic:
- List lighting space types that have no daylighting control requirements: `not_applicable_space_types = ["DORMITORY_LIVING_QUARTERS", "FIRE_STATION_SLEEPING_QUARTERS", "HEALTHCARE_FACILITY_OPERATING_ROOM", "OUTPATIENT_HEALTH_CARE_FACILITIES_CLASS_1_IMAGING_ROOMS", "DWELLING_UNIT", "GUEST_ROOM", "STORAGE_ROOM_SMALL", "PARKING_AREA_INTERIOR", "NONE"]`

- Check if each zone has window or skylight in the building segment in the Proposed model: `For zone_p in P_RMD...zones:`

- Initialize not-applicable space with lighting power flag as FALSE: `na_space_with_lighting_power_flag = FALSE`

Comment thread
JacksonJ-KC marked this conversation as resolved.
- Check if each zone has window or skylight in the building segment in the Proposed model: `For zone_p in P_RMR...zones:`
- For each space in zone, compute total lighting power density and set flag if not-applicable space has lighting power:
`if space.lighting_space_type in not_applicable_space_types and sum(lighting.power_per_area for lighting in space.interior_lighting) > 0: na_space_with_lighting_power_flag = TRUE`

- Check if all spaces in the zone are in the list of not_applicable space types and no not-applicable space has lighting power, if so, skip the zone:
`if all(space.lighting_space_type in not_applicable_space_types for space in zone_p.spaces) and not na_space_with_lighting_power_flag: continue`

- For each surfaces in zone: `surface_p in zone_p.surfaces`

Expand All @@ -31,20 +39,21 @@

**Rule Assertion:** For each zone in the Proposed model:

- Case 1, if the zone has window or skylight and daylight control, and daylight control is not modeled using schedule: `if ( daylight_flag_p == TRUE ) AND ( has_daylight_control_flag == TRUE ) AND ( NOT daylight_schedule_adjustment_flag ): UNDETERMINED and raise_warning "SOME OF THE SPACES IN ZONE ARE MODELED WITH WINDOW(S) AND/OR SKYLIGHT(S) AND HAVE DAYLIGHTING CONTROLS MODELED EXPLICITLY IN THE SIMULATION TOOL. VERIFY THAT THE MANDATORY LIGHTING CONTROL REQUIREMENTS ARE MET."`
- Case 1, if the zone contains a not-applicable space type with lighting power: `if na_space_with_lighting_power_flag: UNDETERMINED and raise_warning "THE ZONE CONTAINS A NOT-APPLICABLE SPACE TYPE WITH LIGHTING POWER. VERIFY THAT THE MANDATORY DAYLIGHTING CONTROL REQUIREMENTS ARE MET, IF APPLICABLE."`

- Case 2, if the zone has window or skylight and daylight control, and daylight control is not modeled using schedule: `if ( daylight_flag_p == TRUE ) AND ( has_daylight_control_flag == TRUE ) AND ( NOT daylight_schedule_adjustment_flag ): UNDETERMINED and raise_warning "SOME OF THE SPACES IN ZONE ARE MODELED WITH WINDOW(S) AND/OR SKYLIGHT(S) AND HAVE DAYLIGHTING CONTROLS MODELED EXPLICITLY IN THE SIMULATION TOOL. VERIFY THAT THE MANDATORY LIGHTING CONTROL REQUIREMENTS ARE MET."`

- Case 2, else if the zone has window or skylight and daylight control, and daylight control is modeled using schedule: `if ( daylight_flag_p == TRUE ) AND ( has_daylight_control_flag == TRUE ) AND ( daylight_schedule_adjustment_flag ): UNDETERMINED and raise_warning "SOME OF THE SPACES IN ZONE ARE MODELED WITH WINDOW(S) AND/OR SKYLIGHT(S) AND HAVE DAYLIGHTING CONTROLS MODELED VIA SCHEDULE ADJUSTMENT. VERIFY THAT THE MANDATORY LIGHTING CONTROL REQUIREMENTS ARE MET, AND THAT THE SUPPORTING DOCUMENTATION IS PROVIDED FOR THE SCHEDULE ADJUSTMENT."`
- Case 3, else if the zone has window or skylight and daylight control, and daylight control is modeled using schedule: `if ( daylight_flag_p == TRUE ) AND ( has_daylight_control_flag == TRUE ) AND ( daylight_schedule_adjustment_flag ): UNDETERMINED and raise_warning "SOME OF THE SPACES IN ZONE ARE MODELED WITH WINDOW(S) AND/OR SKYLIGHT(S) AND HAVE DAYLIGHTING CONTROLS MODELED VIA SCHEDULE ADJUSTMENT. VERIFY THAT THE MANDATORY LIGHTING CONTROL REQUIREMENTS ARE MET, AND THAT THE SUPPORTING DOCUMENTATION IS PROVIDED FOR THE SCHEDULE ADJUSTMENT."`

- Case 3, else if the zone has window or skylight and daylight control is not modeled: `else if ( daylight_flag_p == TRUE ) AND ( has_daylight_control_flag == FALSE ): FAIL and raise_warning "SOME OF THE SPACES IN ZONE ARE MODELED WITH FENESTRATION BUT NO DAYLIGHTING CONTROLS. THE DESIGN MUST INCLUDE MANDATORY DAYLIGHTING CONTROLS UNLESS ANY OF THE EXCEPTIONS TO 90.1 SECTION 9.4.1.1(E) APPLY."`
- Case 4, else if the zone has window or skylight and daylight control is not modeled: `else if ( daylight_flag_p == TRUE ) AND ( has_daylight_control_flag == FALSE ): FAIL and raise_warning "SOME OF THE SPACES IN ZONE ARE MODELED WITH FENESTRATION BUT NO DAYLIGHTING CONTROLS. THE DESIGN MUST INCLUDE MANDATORY DAYLIGHTING CONTROLS UNLESS ANY OF THE EXCEPTIONS TO 90.1 SECTION 9.4.1.1(E) APPLY."`

- Case 4, else if the zone does not have window or skylight and daylight control is modeled: `else if ( daylight_flag_p == FALSE ) AND ( has_daylight_control_flag == TRUE ): FAIL`
- Case 5, else if the zone does not have window or skylight and daylight control is modeled: `else if ( daylight_flag_p == FALSE ) AND ( has_daylight_control_flag == TRUE ): FAIL`

- Case 5, else, the zone does not have window or skylight and no daylight control is modeled: `else: PASS`
- Case 6, else, the zone does not have window or skylight and no daylight control is modeled: `else: PASS`

**Notes:**
1. Updated the Rule ID from 6-12 to 6-8 on 6/3/2022
2. Updated the Rule ID from 6-8 to 6-7 on 6/8/2022
3. The rule has been written to apply to user RMR, it should instead be implemented to apply to P-RMR- should discuss

3. Lighting space types that have no daylighting control requirements are taken from Table 9.6.1 rows with no REQ under the daylighting control columns.

**[Back](../_toc.md)**
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -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",
],
)
1 change: 1 addition & 0 deletions rct229/rulesets/ashrae9012019/data_fns/table_G3_7_fns.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
139 changes: 110 additions & 29 deletions rct229/rulesets/ashrae9012019/section6/section6rule7.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,15 @@
from rct229.schema.schema_enums import SchemaEnums
from rct229.utils.jsonpath_utils import find_all

MSG_WARN_NA_SPACE_WITH_LIGHTING = "The zone contains a not-applicable space type with lighting power. Verify that the mandatory daylighting control requirements are met, if applicable."
MSG_WARN_DAYLIGHT_NO_SCHEDULE = "Some of the spaces in zone are modeled with window(s) and/or skylight(s) and have daylighting controls modeled explicitly in the simulation tool. Verify that the mandatory lighting control requirements are met."
MSG_WARN_DAYLIGHT = "Some of the spaces in zone are modeled with window(s) and/or skylight(s) and have daylighting controls modeled via schedule adjustment. Verify that the mandatory lighting control requirements are met, and that the supporting documentation is provided for the schedule adjustment."
MSG_WARN_NO_DAYLIGHT = "Some of the spaces in zone are modeled with fenestration but no daylighting controls. The design must include mandatory daylighting controls unless any of the exceptions to 90.1 section 9.4.1.1 apply."

VentilationSpaceOptions = SchemaEnums.schema_enums[
"VentilationSpaceOptions2019ASHRAE901"
]
LightingSpaceOptions = SchemaEnums.schema_enums["LightingSpaceOptions2019ASHRAE901TG37"]
DOOR = SchemaEnums.schema_enums["SubsurfaceClassificationOptions"].DOOR
EXTERIOR = SchemaEnums.schema_enums["SurfaceAdjacencyOptions"].EXTERIOR
NONE = SchemaEnums.schema_enums["LightingDaylightingControlOptions"].NONE
Expand All @@ -32,6 +37,44 @@ def __init__(self):
list_path="ruleset_model_descriptions[0].buildings[*].building_segments[*].zones[*]",
)

def list_filter(self, context_item, data):
zone_p = context_item.PROPOSED

not_applicable_space_types = {
LightingSpaceOptions.DORMITORY_LIVING_QUARTERS,
LightingSpaceOptions.FIRE_STATION_SLEEPING_QUARTERS,
LightingSpaceOptions.HEALTHCARE_FACILITY_OPERATING_ROOM,
VentilationSpaceOptions.OUTPATIENT_HEALTH_CARE_FACILITIES_CLASS_1_IMAGING_ROOMS,
LightingSpaceOptions.DWELLING_UNIT,
LightingSpaceOptions.GUEST_ROOM,
LightingSpaceOptions.STORAGE_ROOM_SMALL,
LightingSpaceOptions.PARKING_AREA_INTERIOR,
LightingSpaceOptions.NONE,
}

spaces = zone_p.get("spaces", [])

na_space_with_lighting_power = any(
(
space.get("lighting_space_type") in not_applicable_space_types
or space.get("ventilation_space_type") in not_applicable_space_types
)
and sum(
il.get("power_per_area", 0) for il in space.get("interior_lighting", [])
)
> 0
for space in spaces
)

# Skip only if all spaces are not applicable and none have lighting power
return not (
all(
space.get("lighting_space_type") in not_applicable_space_types
for space in spaces
)
and not na_space_with_lighting_power
)

class ZoneRule(RuleDefinitionBase):
def __init__(self):
super(PRM9012019Rule66m62.ZoneRule, self).__init__(
Expand All @@ -44,71 +87,109 @@ def __init__(self):
def get_calc_vals(self, context, data=None):
zone_p = context.PROPOSED

daylight_flag_p = (
not_applicable_space_types = {
LightingSpaceOptions.DORMITORY_LIVING_QUARTERS,
LightingSpaceOptions.FIRE_STATION_SLEEPING_QUARTERS,
LightingSpaceOptions.HEALTHCARE_FACILITY_OPERATING_ROOM,
VentilationSpaceOptions.OUTPATIENT_HEALTH_CARE_FACILITIES_CLASS_1_IMAGING_ROOMS,
LightingSpaceOptions.DWELLING_UNIT,
LightingSpaceOptions.GUEST_ROOM,
LightingSpaceOptions.STORAGE_ROOM_SMALL,
LightingSpaceOptions.PARKING_AREA_INTERIOR,
LightingSpaceOptions.NONE,
}

has_na_space_with_lighting_power = any(
(
space.get("lighting_space_type") in not_applicable_space_types
or space.get("ventilation_space_type") in not_applicable_space_types
)
and sum(
il.get("power_per_area", 0)
for il in space.get("interior_lighting", [])
)
> 0
for space in zone_p.get("spaces", [])
)

is_daylighting_control_expected = (
len(
find_all(
# Doors in a surface adjacent to exterior
f'$.surfaces[*][?(@.adjacent_to = "{EXTERIOR}")].subsurfaces[*][?(@.classification != "{DOOR}")]',
f'$.surfaces[*][?(@.adjacent_to = "{EXTERIOR}")].'
f'subsurfaces[*][?(@.classification != "{DOOR}")]',
zone_p,
)
)
> 0
)

has_daylight_control_flag = (
is_daylighting_control_modeled = (
len(
find_all(
# interior_lighting instances with daylighting_control_type set to NONE
f'$.spaces[*].interior_lighting[*][?(@.daylighting_control_type!= "{NONE}")]',
f"$.spaces[*].interior_lighting[*]"
f'[?(@.daylighting_control_type != "{NONE}")]',
zone_p,
)
)
> 0
)

daylight_schedule_adjustment_flag = any(
find_all(
# interior_lighting instances with are_schedules_used_for_modeling_daylighting_control set to True
"$.spaces[*].interior_lighting[*][?(@.are_schedules_used_for_modeling_daylighting_control = true)]",
zone_p,
are_schedules_used_for_modeling_daylighting_controls = (
len(
find_all(
"$.spaces[*].interior_lighting[*]"
"[?(@.are_schedules_used_for_modeling_daylighting_control = true)]",
zone_p,
)
)
> 0
)

return {
"daylight_flag_p": daylight_flag_p,
"has_daylight_control_flag": has_daylight_control_flag,
"daylight_schedule_adjustment_flag": daylight_schedule_adjustment_flag,
"na_space_with_lighting_power": has_na_space_with_lighting_power,
"is_daylighting_control_expected": is_daylighting_control_expected,
"is_daylighting_control_modeled": is_daylighting_control_modeled,
"are_schedules_used_for_modeling_daylighting_controls": (
are_schedules_used_for_modeling_daylighting_controls
),
}

def manual_check_required(self, context, calc_vals=None, data=None):
daylight_flag_p = calc_vals["daylight_flag_p"]
has_daylight_control_flag = calc_vals["has_daylight_control_flag"]

return daylight_flag_p and has_daylight_control_flag
return calc_vals["na_space_with_lighting_power"] or (
calc_vals["is_daylighting_control_expected"]
and calc_vals["is_daylighting_control_modeled"]
)

def get_manual_check_required_msg(self, context, calc_vals=None, data=None):
daylight_schedule_adjustment_flag = calc_vals[
"daylight_schedule_adjustment_flag"
]
if calc_vals["na_space_with_lighting_power"]:
return MSG_WARN_NA_SPACE_WITH_LIGHTING

return (
MSG_WARN_DAYLIGHT
if daylight_schedule_adjustment_flag
if calc_vals["are_schedules_used_for_modeling_daylighting_controls"]
else MSG_WARN_DAYLIGHT_NO_SCHEDULE
)

def rule_check(self, context, calc_vals, data=None):
daylight_flag_p = calc_vals["daylight_flag_p"]
has_daylight_control_flag = calc_vals["has_daylight_control_flag"]
def rule_check(self, context, calc_vals=None, data=None):
is_daylighting_control_expected = calc_vals[
"is_daylighting_control_expected"
]
is_daylighting_control_modeled = calc_vals["is_daylighting_control_modeled"]

return not daylight_flag_p and not has_daylight_control_flag
return (
not is_daylighting_control_expected
and not is_daylighting_control_modeled
)

def get_fail_msg(self, context, calc_vals=None, data=None):
daylight_flag_p = calc_vals["daylight_flag_p"]
has_daylight_control_flag = calc_vals["has_daylight_control_flag"]
is_daylighting_control_expected = calc_vals[
"is_daylighting_control_expected"
]
is_daylighting_control_modeled = calc_vals["is_daylighting_control_modeled"]

return (
MSG_WARN_NO_DAYLIGHT
if daylight_flag_p and not has_daylight_control_flag
if is_daylighting_control_expected
and not is_daylighting_control_modeled
else ""
)
8 changes: 5 additions & 3 deletions rct229/schema/Enumerations2019ASHRAE901.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -467,7 +469,7 @@
null,
null,
null,
null
"Indicates that the space will have no occupancy, such as an elevator shaft."
]
},
"LightingPurposeOptions2019ASHRAE901": {
Expand Down
Loading