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-8 #1569

Closed
wants to merge 16 commits into from
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
4 changes: 2 additions & 2 deletions docs/section11/Rule11-6.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
**Schema Version:** 0.0.37
**Mandatory Rule:** True
**Rule ID:** 11-6
**Rule Description:** Piping losses shall not be modeled.
**Rule Description:** Piping losses shall not be modeled.
**Rule Assertion:** Options are PASS/FAIL/NOT_APPLICABLE/UNDETERMINED
**Appendix G Section Reference:** Table G3.1 #11, baseline column, i

Expand All @@ -26,7 +26,7 @@
- set the piping_losses_modeled to true and go directly to rule assertion: `piping_losses_modeled = true: GO TO RULE_ASSERTION`

- **Rule Assertion - Zone:**
- Case1: piping losses are not modeled, PASS: `if !piping_losses_modeled: PASS`
- Case1: piping losses are not modeled, PASS: `if piping_losses_modeled == False: PASS`
- Case2: piping losses are modeled, FAIL: `else: FAIL`


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from rct229.rulesets.ashrae9012019.ruleset_functions.get_energy_required_to_heat_swh_use import (
get_energy_required_to_heat_swh_use,
)

from rct229.utils.assertions import getattr_
from rct229.utils.jsonpath_utils import find_all
from rct229.utils.pint_utils import ZERO
from rct229.utils.utility_functions import (
Expand Down Expand Up @@ -75,7 +75,9 @@ def get_swh_components_associated_with_each_swh_bat(
rmd, distribution_id
)
)
tanks = distribution.get("tanks")
tanks = getattr_(
distribution, "service_water_heating_distribution_systems", "tanks"
)
for tank in tanks:
swh_and_equip_dict[swh_bat].tanks.append(tank["id"])

Expand All @@ -101,7 +103,12 @@ def get_swh_components_associated_with_each_swh_bat(
in swh_and_equip_dict[swh_bat].swh_distribution
):
swh_and_equip_dict[swh_bat].swh_heating_eq.append(swh_equip["id"])
for solar_t in swh_equip.get("solar_thermal_systems"):
getattr_(
swh_equip,
"service_water_heating_equipment",
"solar_thermal_systems",
)
for solar_t in swh_equip["solar_thermal_systems"]:
swh_and_equip_dict[swh_bat].solar_thermal.append(solar_t["id"])

return swh_and_equip_dict
2 changes: 1 addition & 1 deletion rct229/rulesets/ashrae9012019/section11/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
# "section11rule5",
# "section11rule6",
# "section11rule7",
# "section11rule8",
"section11rule8",
# "section11rule9",
# "section11rule10",
# "section11rule11",
Expand Down
85 changes: 85 additions & 0 deletions rct229/rulesets/ashrae9012019/section11/section11rule6.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
from rct229.rule_engine.rule_base import RuleDefinitionBase
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.rulesets.ashrae9012019.ruleset_functions.get_swh_uses_associated_with_each_building_segment import (
get_swh_uses_associated_with_each_building_segment,
)
from rct229.utils.jsonpath_utils import find_all, find_exactly_one_with_field_value


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

def __init__(self):
super(Section11Rule6, self).__init__(
rmds_used=produce_ruleset_model_description(
USER=False, BASELINE_0=True, PROPOSED=False
),
each_rule=Section11Rule6.RMDRule(),
index_rmd=BASELINE_0,
id="11-6",
description="Piping losses shall not be modeled.",
ruleset_section_title="Service Water Heating",
standard_section="Table G3.1 #11, baseline column, i",
is_primary_rule=True,
list_path="ruleset_model_descriptions[0]",
)

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

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

return {"rmd_b": rmd_b}

class BuildingSegmentRule(RuleDefinitionBase):
def __init__(self):
super(Section11Rule6.RMDRule.BuildingSegmentRule, self).__init__(
rmds_used=produce_ruleset_model_description(
USER=False,
BASELINE_0=True,
PROPOSED=False,
),
)

def get_calc_vals(self, context, data=None):
rmd_b = data["rmd_b"]
building_segment_b = context.BASELINE_0

swh_distribution_and_eq_list = (
get_swh_uses_associated_with_each_building_segment(
rmd_b, building_segment_b["id"]
)
)

for piping_id in swh_distribution_and_eq_list:
service_water_piping_b = find_exactly_one_with_field_value(
"$.service_water_heating_distribution_systems[*]",
"id",
piping_id,
rmd_b,
)

piping_losses_modeled_b = any(
find_all(
"$.service_water_piping[*].are_thermal_losses_modeled",
service_water_piping_b,
)
)

return {"piping_losses_modeled_b": piping_losses_modeled_b}

def rule_check(self, context, calc_vals=None, data=None):
piping_losses_modeled_b = calc_vals["piping_losses_modeled_b"]

return not piping_losses_modeled_b
226 changes: 226 additions & 0 deletions rct229/rulesets/ashrae9012019/section11/section11rule8.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
from rct229.rule_engine.rule_base import RuleDefinitionBase
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.rulesets.ashrae9012019.ruleset_functions.get_swh_bats_and_swh_use import (
get_swh_bats_and_swh_use,
)
from rct229.rulesets.ashrae9012019.ruleset_functions.get_swh_components_associated_with_each_swh_bat import (
get_swh_components_associated_with_each_swh_bat,
)
from rct229.rulesets.ashrae9012019.ruleset_functions.get_swh_equipment_type import (
get_swh_equipment_type,
)
from rct229.schema.schema_enums import SchemaEnums
from rct229.utils.jsonpath_utils import find_all

SERVICE_WATER_HEATING_SPACE = SchemaEnums.schema_enums[
"ServiceWaterHeatingSpaceOptions2019ASHRAE901"
]

CASE3_MSG = (
"The Service Water Heating Building Area type for this building segment is undetermined, and there are multiple building segments in the project. "
"Therefore it cannot be determined whether this building segment shares a service water heating building area type with one of the other building segments."
)
CASE4_MSG = (
"The Service Water Heating Building Area Type is 'OTHER' and is applied to multiple building segments. "
"'OTHER' can describe multiple Service Water Heating Building Area Types. "
"Confirm that Service Water Heating Building Area Type is provided with one and only one service water heating system."
)


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

def __init__(self):
super(Section11Rule8, self).__init__(
rmds_used=produce_ruleset_model_description(
USER=False, BASELINE_0=True, PROPOSED=True
),
each_rule=Section11Rule8.RMDRule(),
index_rmd=BASELINE_0,
id="11-8",
description="One system per building area type shall be modeled in the baseline.",
ruleset_section_title="Service Water Heating",
standard_section="Table G3.1 #11, baseline column, a + b",
is_primary_rule=True,
list_path="ruleset_model_descriptions[0]",
required_fields={"$": ["calendar"], "$.calendar": ["is_leap_year"]},
data_items={"is_leap_year": (BASELINE_0, "calendar/is_leap_year")},
)

class RMDRule(RuleDefinitionListIndexedBase):
def __init__(self):
super(Section11Rule8.RMDRule, self).__init__(
rmds_used=produce_ruleset_model_description(
USER=False,
BASELINE_0=True,
PROPOSED=True,
),
index_rmd=BASELINE_0,
each_rule=Section11Rule8.RMDRule.SWHBATRule(),
)

def create_data(self, context, data):
rmd_p = context.PROPOSED
rmd_b = context.BASELINE_0
is_leap_year_b = data["is_leap_year"]

num_of_bldg_segment_b = len(
find_all("$.buildings[*].building_segments[*]", rmd_b)
)

service_water_heating_uses_p = {
swh_use["id"]: swh_use.get("use", 0.0)
for swh_use in find_all(
"$.buildings[*].building_segments[*].zones[*].spaces[*].service_water_heating_uses[*]",
rmd_p,
)
}

swh_equip_type_b = {
swh_equip_id: get_swh_equipment_type(rmd_b, swh_equip_id)
for swh_equip_id in find_all(
"$.service_water_heating_equipment[*].id", rmd_b
)
}

swh_bats_and_uses_b = get_swh_components_associated_with_each_swh_bat(
rmd_b, is_leap_year_b
)

num_swh_systems_b = {
swh_bat: len(swh_use.swh_distribution)
for swh_bat, swh_use in swh_bats_and_uses_b.items()
}
num_swh_equipment_this_use_b = {
swh_bat: len(swh_use.swh_heating_eq)
for swh_bat, swh_use in swh_bats_and_uses_b.items()
}

swh_bats_and_uses_p = get_swh_bats_and_swh_use(rmd_p)

building_area_type_SWH_equip_dict_b = {}
building_area_type_and_uses_p = {}
for bat_type, SWH_Equipment_Associations in swh_bats_and_uses_b.items():
building_area_type_SWH_equip_dict_b[bat_type] = {}
building_area_type_SWH_equip_dict_b[bat_type]["id"] = bat_type
building_area_type_SWH_equip_dict_b[bat_type][
"SWH_Equipment_Associations"
] = SWH_Equipment_Associations

building_area_type_and_uses_p[bat_type] = {}
building_area_type_and_uses_p[bat_type]["id"] = bat_type
building_area_type_and_uses_p[bat_type][
"swh_bats_and_uses_p"
] = swh_bats_and_uses_p[bat_type]

return {
"num_of_bldg_segment_b": num_of_bldg_segment_b,
"num_swh_systems_b": num_swh_systems_b,
"num_swh_equipment_this_use_b": num_swh_equipment_this_use_b,
"swh_bats_and_uses_b": swh_bats_and_uses_b,
"service_water_heating_uses_p": service_water_heating_uses_p,
"swh_equip_type_b": swh_equip_type_b,
"building_area_type_SWH_equip_dict_b": building_area_type_SWH_equip_dict_b,
"building_area_type_and_uses_p": building_area_type_and_uses_p,
}

def create_context_list(self, context, data=None):
building_area_type_SWH_equip_dict_b = data[
"building_area_type_SWH_equip_dict_b"
]
building_area_type_and_uses_p = data["building_area_type_and_uses_p"]

return [
produce_ruleset_model_description(
USER=False,
BASELINE_0=building_area_type_SWH_equip_dict_b[bat_type],
PROPOSED=building_area_type_and_uses_p[bat_type],
)
for bat_type, SWH_Equipment_Associations in building_area_type_SWH_equip_dict_b.items()
]

class SWHBATRule(RuleDefinitionBase):
def __init__(self):
super(Section11Rule8.RMDRule.SWHBATRule, self).__init__(
rmds_used=produce_ruleset_model_description(
USER=False, BASELINE_0=True, PROPOSED=True
),
)

def is_applicable(self, context, data=None):
building_area_type_and_uses_p_b = context.PROPOSED
service_water_heating_uses_p = data["service_water_heating_uses_p"]

return all(
[
service_water_heating_uses_p[swh_uses_id_p] > 0.0
for swh_uses_id_p in building_area_type_and_uses_p_b[
"swh_bats_and_uses_p"
]
]
)

def get_calc_vals(self, context, data=None):
swh_bats_and_equip_dict_this_use = context.BASELINE_0
num_of_bldg_segment_b = data["num_of_bldg_segment_b"]
swh_bats_and_uses_b = data["swh_bats_and_uses_b"]

swh_bat_b = swh_bats_and_equip_dict_this_use["id"]

num_swh_systems_b = data["num_swh_systems_b"][swh_bat_b]
num_swh_equipment_this_use_b = data["num_swh_equipment_this_use_b"][
swh_bat_b
]

is_referenced_in_other_bats = False
if num_swh_systems_b == 1:
swh_dist_id = swh_bats_and_uses_b[swh_bat_b].swh_distribution[0]
for other_swh_bat in swh_bats_and_uses_b:
if other_swh_bat != swh_bat_b:
if (
swh_dist_id
in swh_bats_and_uses_b[swh_bat_b].swh_distribution
):
is_referenced_in_other_bats = True

if swh_bat_b == SERVICE_WATER_HEATING_SPACE.ALL_OTHERS:
multiple_segments_with_bat_other = False

return {
"num_of_bldg_segment_b": num_of_bldg_segment_b,
"is_referenced_in_other_bats": is_referenced_in_other_bats,
"multiple_segments_with_bat_other": multiple_segments_with_bat_other,
}

def manual_check_required(self, context, calc_vals=None, data=None):
shw_bat_b = calc_vals["shw_bat_b"]
multiple_segments_with_bat_other = calc_vals[
"multiple_segments_with_bat_other"
]

return shw_bat_b == "UNDETERMINED" or multiple_segments_with_bat_other

def get_manual_check_required_msg(self, context, calc_vals=None, data=None):
shw_bat_b = calc_vals["shw_bat_b"]
multiple_segments_with_bat_other = calc_vals[
"multiple_segments_with_bat_other"
]

UNDETERMINED_MSG = ""
if shw_bat_b == "UNDETERMINED":
UNDETERMINED_MSG = CASE3_MSG
elif not multiple_segments_with_bat_other:
UNDETERMINED_MSG = CASE4_MSG

return UNDETERMINED_MSG

def rule_check(self, context, calc_vals=None, data=None):
shw_bat = calc_vals["shw_bat"]
num_of_bldg_segment_b = calc_vals["num_of_bldg_segment_b"]
is_referenced_in_other_bats = calc_vals["is_referenced_in_other_bats "]

return (
shw_bat == "UNDETERMINED" and num_of_bldg_segment_b == 1
) or not is_referenced_in_other_bats
Loading
Loading