Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RS/YJ/Rule 11-12 (include only necessary codes) #1554

Merged
merged 11 commits into from
Nov 20, 2024
Merged
6 changes: 3 additions & 3 deletions docs/section11/Rule11-12.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@

**Appendix G Section Reference:** Table G3.1 #11, baseline column, d + exception

**Evaluation Context:** B_RMD - each building
**Evaluation Context:** B_RMD - each building
**Data Lookup:**
**Function Call:**
**Function Call:**
- **get_component_by_id**

**Applicability Checks:**
Expand All @@ -28,7 +28,7 @@
- check to see if the schedule is operating 24hrs per day, all days per year: `if sum(operation_schedule.hourly_values) == hours_this_year:`
- only projects with SWH in the proposed model are interpreted as having SWH loads. A building must both have SWH loads and a 24hr operating schedule for this rule to be applicable.
- look at each building segment in the building: `for building_segment in building.building_segments:`
- get the service water heating uses in the building segment `service_water_heating_use_ids = get_SWH_uses_associated_with_each_building_segment(P_RMD, building_segment.id)`
- get the service water heating uses in the building segment `service_water_heating_use_ids = get_SWH_uses_associated_with_each_building_segment(P_RMD)`
- look at each service water heating use id: `for swh_use_id in service_water_heating_use_ids:`
- get the swh_use using get_component_by_ID: `swh_use = get_component_by_ID(P_RMD, swh_use_id)`
- check to see if the use has SWH loads: `if swh_use.use > 0:`
Expand Down
2 changes: 1 addition & 1 deletion rct229/rulesets/ashrae9012019/section11/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# "section11rule9",
# "section11rule10",
"section11rule11",
# "section11rule12",
"section11rule12",
# "section11rule13",
# "section11rule14",
# "section11rule15",
Expand Down
141 changes: 141 additions & 0 deletions rct229/rulesets/ashrae9012019/section11/section11rule12.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
from rct229.rule_engine.partial_rule_definition import PartialRuleDefinition
from rct229.rule_engine.rule_list_indexed_base import RuleDefinitionListIndexedBase
from rct229.rule_engine.ruleset_model_factory import produce_ruleset_model_description
from rct229.rule_engine.rulesets import LeapYear
from rct229.rulesets.ashrae9012019 import BASELINE_0
from rct229.rulesets.ashrae9012019.ruleset_functions.get_swh_uses_associated_with_each_building_segment import (
get_swh_uses_associated_with_each_building_segment,
)
from rct229.utils.assertions import getattr_
from rct229.utils.jsonpath_utils import find_all, find_one

APPLICABILITY_MSG = (
"This building is a 24hr-facility with service water heating loads. If the building meets the prescriptive criteria for use of condenser heat recovery systems described in 90.1 Section 6.5.6.2, a system meeting the requirements of that section shall be included in the baseline building design regardless of the exceptions to Section 6.5.6.2. "
"(Exceptions: 1. Facilities that employ condenser heat recovery for space heating with a heat recovery design exceeding 30% of the peak water-cooled condenser load at design conditions."
" 2. Facilities that provide 60% of their service water heating from site-solar energy or siterecovered energy or from other sources.) Recommend manual review to determine if project complies."
)


class Section11Rule12(RuleDefinitionListIndexedBase):
"""Rule 12 of ASHRAE 90.1-2019 Appendix G Section 11 (Service Water Heating)"""

def __init__(self):
super(Section11Rule12, self).__init__(
rmds_used=produce_ruleset_model_description(
USER=False, BASELINE_0=True, PROPOSED=True
),
each_rule=Section11Rule12.RMDRule(),
index_rmd=BASELINE_0,
id="11-12",
description="For large, 24-hour-per-day facilities that meet the prescriptive criteria for use of condenser heat recovery systems described in Section 6.5.6.2, a system meeting the requirements of that section shall be included in the baseline building design regardless of the exceptions to Section 6.5.6.2.",
ruleset_section_title="Service Water Heating",
standard_section="Table G3.1 #11, baseline column, d + exception",
is_primary_rule=False,
list_path="ruleset_model_descriptions[0]",
data_items={"is_leap_year_b": (BASELINE_0, "calendar/is_leap_year")},
)

class RMDRule(RuleDefinitionListIndexedBase):
def __init__(self):
super(Section11Rule12.RMDRule, self).__init__(
rmds_used=produce_ruleset_model_description(
USER=False, BASELINE_0=True, PROPOSED=True
),
each_rule=Section11Rule12.RMDRule.BuildingRule(),
index_rmd=BASELINE_0,
list_path="$.buildings[*]",
)

def create_data(self, context, data):
rmd_b = context.BASELINE_0
rmd_p = context.PROPOSED

swh_uses_associated_with_each_building_segment_p = (
get_swh_uses_associated_with_each_building_segment(rmd_p)
)

return {
"is_leap_year_b": data["is_leap_year_b"],
"schedules_b": find_all("$.schedules[*]", rmd_b),
"schedules_p": find_all("$.schedules[*]", rmd_p),
"swh_uses_associated_with_each_building_segment_p": swh_uses_associated_with_each_building_segment_p,
}

class BuildingRule(PartialRuleDefinition):
def __init__(self):
super(Section11Rule12.RMDRule.BuildingRule, self).__init__(
rmds_used=produce_ruleset_model_description(
USER=False, BASELINE_0=True, PROPOSED=True
),
manual_check_required_msg=APPLICABILITY_MSG,
)

def is_applicable(self, context, data=None):
building_b = context.BASELINE_0
building_p = context.PROPOSED
schedules_b = data["schedules_b"]
is_leap_year_b = data["is_leap_year_b"]

# TODO revise the json path if the service_water_heating_uses is relocated in the schema
service_water_heating_uses_p = find_all(
"$.building_segments[*].zones[*].spaces[*].service_water_heating_uses[*]",
building_p,
)

building_open_schedule_id_p = find_one(
"$.building_open_schedule", building_p
)

bldg_open_sch_id_b = getattr_(
building_b, "buildings", "building_open_schedule"
)

bldg_open_sch_b = next(
(
schedule_b["hourly_values"]
for schedule_b in schedules_b
if schedule_b["id"] == bldg_open_sch_id_b
),
[],
)

hours_this_year = (
LeapYear.LEAP_YEAR_HOURS
if is_leap_year_b
else LeapYear.REGULAR_YEAR_HOURS
)

return (
service_water_heating_uses_p
and building_open_schedule_id_p is not None
and sum(bldg_open_sch_b) == hours_this_year
)

def get_calc_vals(self, context, data=None):
swh_uses_associated_with_each_building_segment_p = data[
"swh_uses_associated_with_each_building_segment_p"
]

uses_associated_with_each_building_segment_p = {
bldg_seg_id: sum(
swh_uses.get("use", 0.0)
for swh_uses in swh_uses_associated_with_each_building_segment_p[
bldg_seg_id
]
)
for bldg_seg_id in swh_uses_associated_with_each_building_segment_p
}

return {
"uses_associated_with_each_building_segment_p": uses_associated_with_each_building_segment_p
}

def applicability_check(self, context, calc_vals, data):
uses_associated_with_each_building_segment_p = calc_vals[
"uses_associated_with_each_building_segment_p"
]

return (
sum(list(uses_associated_with_each_building_segment_p.values()))
> 0.0
)
Loading
Loading