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 22-12 #1156

Merged
merged 5 commits into from
Oct 11, 2023
Merged
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
18 changes: 9 additions & 9 deletions docs/section22/Rule22-12.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
**Rule Description:** The heat rejection system shall be a single loop, modeled with a single cooling tower
**Rule Assertion:** B-RMR = expected value
**Appendix G Section:** Section 22 CHW&CW Loop
**90.1 Section Reference:** G3.1.3.11
**90.1 Section Reference:** G3.1.3.11
**Data Lookup:** None
**Evaluation Context:** Each Heat Rejection Loop
**Applicability Checks:**
Expand All @@ -21,29 +21,29 @@

**Applicability Checks:**

- The function get_heat_rejection_loops_connected_to_baseline_systems() returns a list of loops that are connected to Type 7,8,12,13,7b,8b,12b. Get the list of applicable heat rejection loops: `heat_rejection_loop_ids = get_heat_rejection_loops_connected_to_baseline_systems(B_RMI)`
- The function get_heat_rejection_loops_connected_to_baseline_systems() returns a list of loops that are connected to Type 7,8,12,13,7b,8b,12b. Get the list of applicable heat rejection loops: `heat_rejection_loop_ids_b = get_heat_rejection_loops_connected_to_baseline_systems(B_RMI)`

- if there is one or more loops on this list, the rule is applicable: `if len(heat_rejection_loop_ids) > 0:`
- if there is one or more loops on this list, the rule is applicable: `if len(heat_rejection_loop_ids_b) > 0:`

- continue to rule logic

- otherwise, rule not applicable: `ELSE: NOT_APPLICABLE`

## Rule Logic:
- create a variable to count the number of heat rejections: `number_of_baseline_heat_rejections = 0`
- create a variable to count the number of heat rejections: `number_of_baseline_heat_rejections_b = 0`

- we are looking for one heat rejection connected to one condensing loop. There might be heat rejections for process loads that are not applicable for this rule, so look at each heat_rejection: `for heat_rejection in B_RMI.heat_rejections:`

- check if the heat rejection is connected to one of the fluid loops in heat_rejection_loop_ids, this tells us that it is not a process load cooling tower: `if heat_rejection.loop.id in heat_rejection_loop_ids:`
- check if the heat rejection is connected to one of the fluid loops in heat_rejection_loop_ids_b, this tells us that it is not a process load cooling tower: `if heat_rejection.loop.id in heat_rejection_loop_ids_b:`

- increment the number_of_baseline_heat_rejections: `number_of_baseline_heat_rejections += 1`
- increment the number_of_baseline_heat_rejections_b: `number_of_baseline_heat_rejections_b += 1`

**Rule Assertion:**
- Case 1: If there is exactly one heat rejection, AND there is exactly one heat rejection loop, PASS: `if number_of_baseline_heat_rejections == 1 AND len(heat_rejection_loop_ids) == 1 : PASS`
- Case 1: If there is exactly one heat rejection, AND there is exactly one heat rejection loop, PASS: `if number_of_baseline_heat_rejections_b == 1 AND len(heat_rejection_loop_ids_b) == 1 : PASS`

- Case 2: Elsif there is exactly one heat rejection, but there is more than one fluid loop, fail and include note: `elsif number_of_baseline_heat_rejections == 1 AND len(heat_rejection_loop_ids) > 1: FAIL; note = "there is more than one condenser loop for this building. There should only be one condenser loop attached to all chillers in the baseline chiller plant"`
- Case 2: Elsif there is exactly one heat rejection, but there is more than one fluid loop, fail and include note: `elsif number_of_baseline_heat_rejections_b == 1 AND len(heat_rejection_loop_ids_b) > 1: FAIL; note = "There is more than one condenser loop for this project. There should only be one condenser loop attached to all chillers in the baseline chiller plant"`

- Case 3: Elsif there is exactly one heat rejection loop, but more than one heat rejection, fail and include note: `elsif number_of_baseline_heat_rejections > 1 AND len(heat_rejection_loop_ids) == 1: FAIL; note = "there is more than one cooling tower for the baseline chiller plant. There should only be one cooling tower attached to the condenser loop"`
- Case 3: Elsif there is exactly one heat rejection loop, but more than one heat rejection, fail and include note: `elsif number_of_baseline_heat_rejections_b > 1 AND len(heat_rejection_loop_ids_b) == 1: FAIL; note = "There is more than one cooling tower for the baseline chiller plant. There should only be one cooling tower attached to the condenser loop"`

- Case 4: Else fail and note: `Else: FAIL; note = "There is more than one cooling tower on this loop and there is more than one condenser loop for the chiller plant. For the baseline chiller plant, there should be only one condenser loop with only one cooling tower."`

Expand Down
1 change: 1 addition & 0 deletions rct229/rulesets/ashrae9012019/section22/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"section22rule9",
"section22rule10",
"section22rule11",
"section22rule12",
"section22rule14",
"section22rule16",
"section22rule19",
Expand Down
86 changes: 86 additions & 0 deletions rct229/rulesets/ashrae9012019/section22/section22rule12.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
from rct229.rule_engine.rule_base import RuleDefinitionBase
from rct229.rule_engine.user_baseline_proposed_vals import UserBaselineProposedVals
from rct229.rulesets.ashrae9012019.ruleset_functions.get_heat_rejection_loops_connected_to_baseline_systems import (
get_heat_rejection_loops_connected_to_baseline_systems,
)
from rct229.utils.assertions import getattr_
from rct229.utils.jsonpath_utils import find_all


class Section22Rule12(RuleDefinitionBase):
"""Rule 12 of ASHRAE 90.1-2019 Appendix G Section 22 (Chilled water loop)"""

def __init__(self):
super(Section22Rule12, self).__init__(
rmrs_used=UserBaselineProposedVals(False, True, False),
id="22-12",
description="The heat rejection system shall be a single loop, modeled with a single cooling tower.",
ruleset_section_title="HVAC - Chiller",
standard_section="Section 22 CHW&CW Loop",
is_primary_rule=True,
rmr_context="ruleset_model_descriptions/0",
)

def is_applicable(self, context, data=None):
rmd_b = context.baseline
heat_rejection_loop_ids_b = (
get_heat_rejection_loops_connected_to_baseline_systems(rmd_b)
)

return heat_rejection_loop_ids_b

def get_calc_vals(self, context, data=None):
rmd_b = context.baseline
heat_rejection_loop_ids_b = (
get_heat_rejection_loops_connected_to_baseline_systems(rmd_b)
)

number_of_baseline_heat_rejections_b = len(
[
heat_rejection_b
for heat_rejection_b in find_all("$.heat_rejections[*]", rmd_b)
if getattr_(heat_rejection_b, "heat_rejections", "loop")
in heat_rejection_loop_ids_b
]
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another way to do it could be:

number_of_baseline_heat_rejections_b = len(
            [
                heat_rejection_b
                for heat_rejection_b in find_all("$.heat_rejections[*]", rmd_b)
                if getattr_(heat_rejection_b, "heat_rejections", "loop")
                in heat_rejection_loop_ids_b
            ]
        )

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! Addressed.


return {
"heat_rejection_loop_ids_b": heat_rejection_loop_ids_b,
"number_of_baseline_heat_rejections_b": number_of_baseline_heat_rejections_b,
}

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

return (
number_of_baseline_heat_rejections_b == 1
and len(heat_rejection_loop_ids_b) == 1
)

def get_fail_msg(self, context, calc_vals=None, data=None):
heat_rejection_loop_ids_b = calc_vals["heat_rejection_loop_ids_b"]
number_of_baseline_heat_rejections_b = calc_vals[
"number_of_baseline_heat_rejections_b"
]
len_heat_rejection_loop_ids_b = len(heat_rejection_loop_ids_b)

if (
number_of_baseline_heat_rejections_b == 1
and len_heat_rejection_loop_ids_b > 1
):
FAIL_MSG = "There is more than one condenser loop for this project. There should only be one condenser loop attached to all chillers in the baseline chiller plant."
elif (
number_of_baseline_heat_rejections_b > 1
and len_heat_rejection_loop_ids_b == 1
):
FAIL_MSG = "There is more than one cooling tower for the baseline chiller plant. There should only be one cooling tower attached to the condenser loop."
else:
FAIL_MSG = (
"There is more than one cooling tower on this loop and there is more than one condenser loop for the chiller plant. "
"For the baseline chiller plant, there should be only one condenser loop with only one cooling tower."
)

return FAIL_MSG
Loading
Loading