Skip to content

Commit

Permalink
finish dev
Browse files Browse the repository at this point in the history
  • Loading branch information
yunjoonjung-PNNL committed Oct 6, 2023
1 parent 89e1165 commit f0c6616
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 15 deletions.
24 changes: 9 additions & 15 deletions docs/section22/Rule22-17.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,36 +30,30 @@
- Else, rule is not applicable to the heat rejection: `else: RULE_NOT_APPLICABLE`

## Rule Logic:

- create a variable additional_note_for_no_shaft_power. If the heat_rejection has the fan_shaft_power data element, this note variable will be a blank string, however if there is no fan_shaft_power, the note will be a string that describes how fan_shaft_power is calculated: `additional_note_for_no_shaft_power = ""`

- set has_fan_shaft_power flag equal to false: `has_fan_shaft_power = false`

- create a variable additional_note_for_no_shaft_power. If the heat_rejection has the fan_shaft_power data element, this note variable will be a blank string, however if there is no fan_shaft_power, the note will be a string that describes how fan_shaft_power is calculated: `set additional_note_for_no_shaft_power = ""`

- check if the heat rejection has fan_shaft_power (not sure the exact python command for this): `if heat_rejection.fan_shaft_power:
- check if the heat rejection has fan_shaft_power (not sure the exact python command for this): `if heat_rejection.fan_shaft_power:`

- set fan_shaft_power equal to heat_rejection.fan_shaft_power: `fan_shaft_power = heat_rejection.fan_shaft_power`

- set has_fan_shaft_power flag equal to true: `has_fan_shaft_power = true`

- otherwise, we need to calculate shaft power based on the motor nameplate power: `else:`

- set fan_shaft_power equal to the heat_rejection.fan_motor_nameplate_power * 0.9 (0.9 is a rule of thumb suggested by Michael Rosenberg in April 2023): `fan_shaft_power = heat_rejection.fan_motor_nameplate_power * 0.9 * heat_rejection.fan_motor_efficiency`

- if the shaft power is not directly entered, we also need to create an additional note to return with the result, describing how the calculation was completed: `addtitional_note_for_no_shaft_power = " *Note: The fan shaft power for " + heat_rejection + " was not given. For this evaluation, the fan shaft power was cacluated using a rule of thumb where fan_shaft_power = fan_motor_nameplate_power * 0.9 * fan_motor_efficiency."

- calculate fan brake horsepower by multiplying the fan shaft power by 0.00134102 (the conversion from Watts to HP): `fan_BHP = fan_shaft_power * 0.00134102`
- if the shaft power is not directly entered, we also need to create an additional note to return with the result, describing how the calculation was completed: `addtitional_note_for_no_shaft_power = "*Note: The fan shaft power for " + heat_rejection + " was not given. For this evaluation, the fan shaft power was calculated using a rule of thumb where fan_shaft_power = fan_motor_nameplate_power * 0.9 * fan_motor_efficiency."`

- get the rated water flow rate (assumed to be gpm): `rated_water_flowrate = heat_rejection.rated_water_flowrate`
- get the rated water flow rate: `rated_water_flowrate = heat_rejection.rated_water_flowrate`

- calculate the efficiency in gpm/hp: `heat_rejection_efficiency = rated_water_flowrate / (fan_BHP)`
- calculate the efficiency: `heat_rejection_efficiency = rated_water_flowrate / fan_shaft_power`

**Rule Assertion - HeatRejection:**

- Case 1: check if the efficiency is greater than the rated efficiency: `if ( ahj_flag AND ( heat_rejection_efficiency > 38.2 )): UNDETERMINED; note = "The project includes a cooling tower. We calculated the cooling tower efficiency to be " + heat_rejection_efficiency + ", which is greater than the required efficiency of 38.2 gpm / hp, resulting in a more stringent baseline. However, it was not possible to verify that the modeling inputs correspond to the rating conditions in Table 6.8.1-7." + addtitional_note_for_no_shaft_power`
- Case 1: check if the efficiency is greater than the rated efficiency: `if ( ahj_flag AND ( heat_rejection_efficiency > 38.2 )): UNDETERMINED; note = "The project includes a cooling tower. We calculated the cooling tower efficiency to be " + heat_rejection_efficiency + ", which is greater than the required efficiency of 38.2 gpm / hp, resulting in a more stringent baseline. However, it was not possible to verify that the modeling inputs correspond to the rating conditions in Table 6.8.1-7." + additional_note_for_no_shaft_power`

- Case 2: elsif the heat_rejection_efficiency equals 38.2 gpm/hp, PASS, but include note: `if ( heat_rejection_efficiency == 38.2 ): UNDETERMINED; note = "The project includes a cooling tower. We calculated the cooling tower efficiency to be correct at 38.2 gpm / hp. However, it was not possible to verify that the modeling inputs correspond to the rating conditions in Table 6.8.1-7." + addtitional_note_for_no_shaft_power`
- Case 2: elsif the heat_rejection_efficiency equals 38.2 gpm/hp, PASS, but include note: `if ( heat_rejection_efficiency == 38.2 ): UNDETERMINED; note = "The project includes a cooling tower. We calculated the cooling tower efficiency to be correct at 38.2 gpm / hp. However, it was not possible to verify that the modeling inputs correspond to the rating conditions in Table 6.8.1-7." + additional_note_for_no_shaft_power`

- Case 3: Else: `else: UNDETERMINED; note = "The project includes a cooling tower. We calculated the cooling tower efficiency to be " + heat_rejection_efficiency + ", which is less than the required efficiency of 38.2 gpm / hp. However, it was not possible to verify that the modeling inputs correspond to the rating conditions in Table 6.8.1-7. Please review the efficiency and ensure that it is correct at the rating conditions as specified in the Table 6.8.1-7." + addtitional_note_for_no_shaft_power`
- Case 3: Else: `else: UNDETERMINED; note = "The project includes a cooling tower. We calculated the cooling tower efficiency to be " + heat_rejection_efficiency + ", which is less than the required efficiency of 38.2 gpm / hp. However, it was not possible to verify that the modeling inputs correspond to the rating conditions in Table 6.8.1-7. Please review the efficiency and ensure that it is correct at the rating conditions as specified in the Table 6.8.1-7." + additional_note_for_no_shaft_power`


**Notes:**
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 @@ -15,6 +15,7 @@
"section22rule11",
"section22rule14",
"section22rule16",
"section22rule17",
"section22rule19",
"section22rule20",
"section22rule21",
Expand Down
128 changes: 128 additions & 0 deletions rct229/rulesets/ashrae9012019/section22/section22rule17.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
from rct229.rule_engine.partial_rule_definition import PartialRuleDefinition
from rct229.rule_engine.rule_list_indexed_base import RuleDefinitionListIndexedBase
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.schema.config import ureg
from rct229.utils.assertions import getattr_
from rct229.utils.pint_utils import ZERO, CalcQ
from rct229.utils.std_comparisons import std_equal

FAN_SHAFT_POWER_FACTOR = 0.9
HEAT_REJ_EFF_LIMIT = 38.2 * ureg("gpm/hp")


class Section22Rule17(RuleDefinitionListIndexedBase):
"""Rule 17 of ASHRAE 90.1-2019 Appendix G Section 22 (Chilled water loop)"""

def __init__(self):
super(Section22Rule17, self).__init__(
rmrs_used=UserBaselineProposedVals(False, True, False),
each_rule=Section22Rule17.HeatRejectionRule(),
index_rmr="baseline",
id="22-17",
description="The baseline heat rejection device shall have an efficiency of 38.2 gpm/hp.",
ruleset_section_title="HVAC - Chiller",
standard_section="Section 22 CHW&CW Loop",
is_primary_rule=False,
rmr_context="ruleset_model_descriptions/0",
list_path="$.heat_rejections[*]",
)

def create_data(self, context, data):
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": heat_rejection_loop_ids_b}

class HeatRejectionRule(PartialRuleDefinition):
def __init__(self):
super(Section22Rule17.HeatRejectionRule, self).__init__(
rmrs_used=UserBaselineProposedVals(False, True, False),
required_fields={
"$": ["rated_water_flowrate"],
},
)

def is_applicable(self, context, data=None):
heat_rejection_b = context.baseline
heat_rejection_loop_ids_b = data["heat_rejection_loop_ids_b"]
heat_rejection_loop_b = getattr_(heat_rejection_b, "loop", "loop")

return heat_rejection_loop_b in heat_rejection_loop_ids_b

def get_calc_vals(self, context, data=None):
heat_rejection_b = context.baseline

fan_shaft_power_b = (
heat_rejection_b["fan_shaft_power"]
if heat_rejection_b.get("fan_shaft_power")
else (
getattr_(
heat_rejection_b, "heat_rejection", "fan_motor_nameplate_power"
)
* FAN_SHAFT_POWER_FACTOR
* getattr_(
heat_rejection_b, "heat_rejection", "fan_motor_efficiency"
)
)
)

rated_water_flowrate_b = heat_rejection_b["rated_water_flowrate"]
heat_rejection_efficiency_b = (
0.0
if fan_shaft_power_b == ZERO.POWER
else rated_water_flowrate_b / fan_shaft_power_b
)

return {
"fan_shaft_power_b": CalcQ("electric_power", fan_shaft_power_b),
"rated_water_flowrate_b": CalcQ(
"volumetric_flow_rate", rated_water_flowrate_b
),
"heat_rejection_efficiency_b": heat_rejection_efficiency_b,
}

def get_manual_check_required_msg(self, context, calc_vals=None, data=None):
heat_rejection_b = context.baseline

additional_note_for_no_shaft_power_b = (
""
if heat_rejection_b.get("fan_shaft_power")
else (
f"*Note: The fan shaft power for {heat_rejection_b['id']} was not given. For this evaluation, the fan shaft power was calculated using a rule of thumb "
f"where fan_shaft_power = fan_motor_nameplate_power * {FAN_SHAFT_POWER_FACTOR} * fan_motor_efficiency."
)
)
heat_rejection_efficiency_b = calc_vals["heat_rejection_efficiency_b"]
heat_rejection_efficiency_in_gpm_per_hp_b = round(
heat_rejection_efficiency_b.to(ureg("gpm/hp")).magnitude, 1
)

if heat_rejection_efficiency_b > HEAT_REJ_EFF_LIMIT:
UNDETERMINED_MSG = (
f"The project includes a cooling tower. We calculated the cooling tower efficiency to be {heat_rejection_efficiency_in_gpm_per_hp_b}, "
f"which is greater than the required efficiency of 38.2 gpm/hp, "
f"resulting in a more stringent baseline. However, it was not possible to verify that the modeling inputs correspond to the rating conditions in Table 6.8.1-7. "
f"{additional_note_for_no_shaft_power_b}"
)
elif std_equal(HEAT_REJ_EFF_LIMIT, heat_rejection_efficiency_b):
UNDETERMINED_MSG = (
f"The project includes a cooling tower. We calculated the cooling tower efficiency to be correct at 38.2 gpm/hp. "
f"However, it was not possible to verify that the modeling inputs correspond to the rating conditions in Table 6.8.1-7. "
f"{additional_note_for_no_shaft_power_b}"
)
else:
UNDETERMINED_MSG = (
f"The project includes a cooling tower. We calculated the cooling tower efficiency to be {heat_rejection_efficiency_in_gpm_per_hp_b}, "
f"which is less than the required efficiency of 38.2 gpm / hp. However, it was not possible to verify that the modeling inputs correspond to the rating conditions in Table 6.8.1-7. "
f"Please review the efficiency and ensure that it is correct at the rating conditions as specified in the Table 6.8.1-7. {additional_note_for_no_shaft_power_b}"
)

return UNDETERMINED_MSG

def rule_check(self, context, calc_vals=None, data=None):
return True

0 comments on commit f0c6616

Please sign in to comment.