From afe8568539d14093b995536cda98ebcf062320b4 Mon Sep 17 00:00:00 2001 From: Christina LaPerle Date: Tue, 23 Sep 2025 15:40:40 -0400 Subject: [PATCH 1/6] New RDS, in progress. --- docs/section22/Rule22-44.md | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 docs/section22/Rule22-44.md diff --git a/docs/section22/Rule22-44.md b/docs/section22/Rule22-44.md new file mode 100644 index 0000000000..fac838ac81 --- /dev/null +++ b/docs/section22/Rule22-44.md @@ -0,0 +1,39 @@ +# CHW & CW - Rule 22-44 + +**Rule ID:** 22-44 +**Rule Description:** Where part-load performance of chillers in the proposed design is not available, and the design temperature across the condenser is 10°F, the performance curves in Normative Appendix J, as referenced in Table J-1, shall be modeled for the specified chiller. +**Rule Assertion:** Proposed RMD = expected value +**Appendix G Section:** Table G3.1 #10b Proposed Column + +**Mandatory Rule:** True +**Evaluation Context:** Each Chiller +**Table Lookup:** 90.1 Appendix J Table J-4 +**Function Call:** +1. is_chiller_performance_app_j() + +## Applicability Check: + +- **Check 1:** Get B-RMD system types: `baseline_hvac_system_dict = get_baseline_system_types(B-RMD)` + +- Check if B-RMD is modeled with at least one air-side system that is Type-7, 8, 11.1, 11.2, 12, 13, 7b, 8b, 11b, 12b, i.e. with air-side system served by chiller(s), continue to the next applicability check: `if any(sys_type in baseline_hvac_system_dict.keys() for sys_type in ["SYS-7", "SYS-8", "SYS-11.1", "SYS-11.2", "SYS-12", "SYS-13", "SYS-7B", "SYS-8B", "SYS-11B", "SYS-12B"]): NEXT_APPLICABILITY_CHECK` + +- Else, rule is not applicable to B-RMD: `else: RULE_NOT_APPLICABLE` + +- Get primary and secondary loops for B-RMD: `primary_secondary_loop_dictionary = get_primary_secondary_loops_dict(B_RMD)` + +- For each chiller in B_RMD: `for chiller in B_RMD...chillers:` + - Store the design temperature across the condenser: `design_temperature_across_condenser = chiller.design_leaving_condenser_temperature - chiiler.design_entering_condenser_temperature` + - Check if chiller is connected to a primary chilled water loop that serves HVAC systems: `if chiller.cooling_loop.id in primary_secondary_loop_dictionary: CHECK_RULE_LOGIC` + + **Rule Assertion:** + - Case 1: all lists of missing or non-matching validation points have a length of zero and the design temperature across the condenser is 10F: PASS: `if is_chiller_performance_app_j(chiller) and design_temperature_across_condenser == 10: PASS` + - Case 2: all lists of missing or non-matching validation points have a length of zero and the design temperature across the condenser is NOT 10F: `elif is_chiller_performance_app_j(chiller) and design_temperature_across_condenser != 10: FAIL` + - Case 3: else when all output data is present for the chiller UNDETERMINED: `else: UNDETERMINED and raise_message "FAIL unless manufacturer full- and part-load data is provided to support the modeled curves.` + - Note to RDS team - if there is missing output data the outcome is also UNDETERMINED with a message indicating that the modeled performance curves could not be evaluated. + +**Notes:** +1. Can we add chiller.design_leaving_condenser_temperature to th schema? +2. Update is_chiller_performance_app_j() to take in which table to reference? + + +**[Back](../_toc.md)** \ No newline at end of file From 3c1e271b49b11548c20569c32eb88adf08c76774 Mon Sep 17 00:00:00 2001 From: Christina LaPerle Date: Wed, 24 Sep 2025 08:25:24 -0400 Subject: [PATCH 2/6] New RDS, in progress. --- docs/section22/Rule22-44.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/section22/Rule22-44.md b/docs/section22/Rule22-44.md index fac838ac81..d42861355d 100644 --- a/docs/section22/Rule22-44.md +++ b/docs/section22/Rule22-44.md @@ -34,6 +34,7 @@ **Notes:** 1. Can we add chiller.design_leaving_condenser_temperature to th schema? 2. Update is_chiller_performance_app_j() to take in which table to reference? +3. This rule needs to be added to the rule Workbook **[Back](../_toc.md)** \ No newline at end of file From a96727c7541e4f86345ced90f5838809a0a690de Mon Sep 17 00:00:00 2001 From: claperle <92933945+claperle@users.noreply.github.com> Date: Mon, 29 Sep 2025 08:37:51 -0400 Subject: [PATCH 3/6] Update Rule22-44.md --- docs/section22/Rule22-44.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/section22/Rule22-44.md b/docs/section22/Rule22-44.md index d42861355d..af65c5bf8d 100644 --- a/docs/section22/Rule22-44.md +++ b/docs/section22/Rule22-44.md @@ -32,9 +32,9 @@ - Note to RDS team - if there is missing output data the outcome is also UNDETERMINED with a message indicating that the modeled performance curves could not be evaluated. **Notes:** -1. Can we add chiller.design_leaving_condenser_temperature to th schema? +1. Can we add chiller.design_leaving_condenser_temperature to the schema? 2. Update is_chiller_performance_app_j() to take in which table to reference? 3. This rule needs to be added to the rule Workbook -**[Back](../_toc.md)** \ No newline at end of file +**[Back](../_toc.md)** From 841e685689838e919706ccc575b9b6f1468f7005 Mon Sep 17 00:00:00 2001 From: Christina LaPerle Date: Tue, 30 Sep 2025 15:04:25 -0400 Subject: [PATCH 4/6] Updated for proposed as opposed to previous baseline logic. --- docs/section22/Rule22-44.md | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/docs/section22/Rule22-44.md b/docs/section22/Rule22-44.md index af65c5bf8d..063b074637 100644 --- a/docs/section22/Rule22-44.md +++ b/docs/section22/Rule22-44.md @@ -4,6 +4,8 @@ **Rule Description:** Where part-load performance of chillers in the proposed design is not available, and the design temperature across the condenser is 10°F, the performance curves in Normative Appendix J, as referenced in Table J-1, shall be modeled for the specified chiller. **Rule Assertion:** Proposed RMD = expected value **Appendix G Section:** Table G3.1 #10b Proposed Column +**Applicability Check** +1. Proposed includes at least one non process chiller **Mandatory Rule:** True **Evaluation Context:** Each Chiller @@ -12,29 +14,21 @@ 1. is_chiller_performance_app_j() ## Applicability Check: - -- **Check 1:** Get B-RMD system types: `baseline_hvac_system_dict = get_baseline_system_types(B-RMD)` - -- Check if B-RMD is modeled with at least one air-side system that is Type-7, 8, 11.1, 11.2, 12, 13, 7b, 8b, 11b, 12b, i.e. with air-side system served by chiller(s), continue to the next applicability check: `if any(sys_type in baseline_hvac_system_dict.keys() for sys_type in ["SYS-7", "SYS-8", "SYS-11.1", "SYS-11.2", "SYS-12", "SYS-13", "SYS-7B", "SYS-8B", "SYS-11B", "SYS-12B"]): NEXT_APPLICABILITY_CHECK` - -- Else, rule is not applicable to B-RMD: `else: RULE_NOT_APPLICABLE` - -- Get primary and secondary loops for B-RMD: `primary_secondary_loop_dictionary = get_primary_secondary_loops_dict(B_RMD)` - -- For each chiller in B_RMD: `for chiller in B_RMD...chillers:` +- For each building segment in P-RMD: `for building_segment in P-RMD...Building.building_segments:` + - For each HVAC system in building segment: `for hvac in building_segment.heating_ventilating_air_conditioning_systems:` + - Save chilled water loop that serves cooling systems to non-process CHW coil loop list (list for all loops connected to cooling coils): `if getattr(hvac, 'cooling_system', None) and getattr(hvac.cooling_system, 'chilled_water_loop', None): non_process_chw_coil_loop_list.append(hvac.cooling_system.chilled_water_loop)` +- For each chiller in B_RMD: `for chiller in B_RMD...chillers:` + - Check if chiller loop serves an HVAC systems, if not, then NOT_APPLICABLE for the chiller: `if chiller.cooling_loop in non_process_chw_coil_loop_list: CHECK_RULE_LOGIC` - Store the design temperature across the condenser: `design_temperature_across_condenser = chiller.design_leaving_condenser_temperature - chiiler.design_entering_condenser_temperature` - - Check if chiller is connected to a primary chilled water loop that serves HVAC systems: `if chiller.cooling_loop.id in primary_secondary_loop_dictionary: CHECK_RULE_LOGIC` - **Rule Assertion:** - - Case 1: all lists of missing or non-matching validation points have a length of zero and the design temperature across the condenser is 10F: PASS: `if is_chiller_performance_app_j(chiller) and design_temperature_across_condenser == 10: PASS` - - Case 2: all lists of missing or non-matching validation points have a length of zero and the design temperature across the condenser is NOT 10F: `elif is_chiller_performance_app_j(chiller) and design_temperature_across_condenser != 10: FAIL` + - Case 1: all lists of missing or non-matching validation points have a length of zero and the design temperature across the condenser is 10F: PASS: `if is_chiller_performance_app_j(chiller, J-1) and design_temperature_across_condenser == 10: PASS` + - Case 2: all lists of missing or non-matching validation points have a length of zero and the design temperature across the condenser is NOT 10F: `elif is_chiller_performance_app_j(chiller, J-1) and design_temperature_across_condenser != 10: FAIL` - Case 3: else when all output data is present for the chiller UNDETERMINED: `else: UNDETERMINED and raise_message "FAIL unless manufacturer full- and part-load data is provided to support the modeled curves.` - Note to RDS team - if there is missing output data the outcome is also UNDETERMINED with a message indicating that the modeled performance curves could not be evaluated. **Notes:** -1. Can we add chiller.design_leaving_condenser_temperature to the schema? -2. Update is_chiller_performance_app_j() to take in which table to reference? -3. This rule needs to be added to the rule Workbook +1. Can we add chiller.design_leaving_condenser_temperature to the schema? Need to make public comment to add. +2. Update is_chiller_performance_app_j() to take in which table to reference? **[Back](../_toc.md)** From 5b4f8a04c75ef92e193830d3916810f33643cac3 Mon Sep 17 00:00:00 2001 From: Christina LaPerle Date: Tue, 30 Sep 2025 15:05:51 -0400 Subject: [PATCH 5/6] Updated for proposed as opposed to previous baseline logic. --- docs/section22/Rule22-44.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/section22/Rule22-44.md b/docs/section22/Rule22-44.md index 063b074637..d8f2030169 100644 --- a/docs/section22/Rule22-44.md +++ b/docs/section22/Rule22-44.md @@ -17,7 +17,7 @@ - For each building segment in P-RMD: `for building_segment in P-RMD...Building.building_segments:` - For each HVAC system in building segment: `for hvac in building_segment.heating_ventilating_air_conditioning_systems:` - Save chilled water loop that serves cooling systems to non-process CHW coil loop list (list for all loops connected to cooling coils): `if getattr(hvac, 'cooling_system', None) and getattr(hvac.cooling_system, 'chilled_water_loop', None): non_process_chw_coil_loop_list.append(hvac.cooling_system.chilled_water_loop)` -- For each chiller in B_RMD: `for chiller in B_RMD...chillers:` +- For each chiller in P_RMD: `for chiller in P_RMD...chillers:` - Check if chiller loop serves an HVAC systems, if not, then NOT_APPLICABLE for the chiller: `if chiller.cooling_loop in non_process_chw_coil_loop_list: CHECK_RULE_LOGIC` - Store the design temperature across the condenser: `design_temperature_across_condenser = chiller.design_leaving_condenser_temperature - chiiler.design_entering_condenser_temperature` **Rule Assertion:** From 18629e752d028df34a73c5caf1c55fce0a4eecba Mon Sep 17 00:00:00 2001 From: Jackson Jarboe <122476654+JacksonJ-KC@users.noreply.github.com> Date: Wed, 8 Oct 2025 18:49:15 -0400 Subject: [PATCH 6/6] ruleset function updates --- docs/section22/Rule22-44.md | 47 ++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/docs/section22/Rule22-44.md b/docs/section22/Rule22-44.md index d8f2030169..219b87cb55 100644 --- a/docs/section22/Rule22-44.md +++ b/docs/section22/Rule22-44.md @@ -9,26 +9,51 @@ **Mandatory Rule:** True **Evaluation Context:** Each Chiller -**Table Lookup:** 90.1 Appendix J Table J-4 +**Table Lookup:** 90.1 Appendix J Table J-1 **Function Call:** -1. is_chiller_performance_app_j() +1. does_chiller_performance_match_curve() ## Applicability Check: - For each building segment in P-RMD: `for building_segment in P-RMD...Building.building_segments:` - For each HVAC system in building segment: `for hvac in building_segment.heating_ventilating_air_conditioning_systems:` - Save chilled water loop that serves cooling systems to non-process CHW coil loop list (list for all loops connected to cooling coils): `if getattr(hvac, 'cooling_system', None) and getattr(hvac.cooling_system, 'chilled_water_loop', None): non_process_chw_coil_loop_list.append(hvac.cooling_system.chilled_water_loop)` - For each chiller in P_RMD: `for chiller in P_RMD...chillers:` - - Check if chiller loop serves an HVAC systems, if not, then NOT_APPLICABLE for the chiller: `if chiller.cooling_loop in non_process_chw_coil_loop_list: CHECK_RULE_LOGIC` - - Store the design temperature across the condenser: `design_temperature_across_condenser = chiller.design_leaving_condenser_temperature - chiiler.design_entering_condenser_temperature` - **Rule Assertion:** - - Case 1: all lists of missing or non-matching validation points have a length of zero and the design temperature across the condenser is 10F: PASS: `if is_chiller_performance_app_j(chiller, J-1) and design_temperature_across_condenser == 10: PASS` - - Case 2: all lists of missing or non-matching validation points have a length of zero and the design temperature across the condenser is NOT 10F: `elif is_chiller_performance_app_j(chiller, J-1) and design_temperature_across_condenser != 10: FAIL` - - Case 3: else when all output data is present for the chiller UNDETERMINED: `else: UNDETERMINED and raise_message "FAIL unless manufacturer full- and part-load data is provided to support the modeled curves.` - - Note to RDS team - if there is missing output data the outcome is also UNDETERMINED with a message indicating that the modeled performance curves could not be evaluated. + - Check if chiller loop serves any HVAC systems, if not, then NOT_APPLICABLE for the chiller: `if chiller["cooling_loop"] in non_process_chw_coil_loop_list: CHECK_RULE_LOGIC` + +## Rule Logic: + + - figure out the set of performance curves needed for the chiller - this should be V, X, Y, Z, AA or AB. Initialize a variable curve_set and set it to "NONE": `curve_set = "NONE"` + - get the chiller rated capacity: `rated_capacity = chiller["rated_capacity"]` + + - Data Table J-1 Lookup - determine the set of performance curves to check based on the chiller type and as shown below: + - if the chiller is air-cooled: `if chiller.get("condensing_loop") is None:` + - if the capacity is less than 150 tons, the curves to check are A and K: `if rated_capacity < 150 tons: curve_set_list = ["A", "K"]` + - if the capacity is greater than or equal to 150 tons, the curves to check are B and L: `else: curve_set_list = ["B", "L"]` + + - if the compressor type is POSITIVE_DISPLACEMENT or SCROLL: `if chiller["compressor_type"] in ["POSITIVE_DISPLACEMENT","SCROLL","SCREW"]:` + - if the capacity is less than 75 tons, the curves to check are C and M: `if rated_capacity < 75 tons: curve_set_list = ["C", "M"]` + - else if the capacity is less than 150 tons, the curves to check are D and N: `elif rated_capacity < 150 tons: curve_set_list = ["D", "N"]` + - else if the capacity is less than 300 tons, the curves to check are E and O: `elif rated_capacity < 300 tons: curve_set_list = ["E", "O"]` + - else if the capacity is less than 600 tons, the curves to check are F and P: `elif rated_capacity < 600 tons: curve_set_list = ["F", "P"]` + - else the capacity is greater than or equal to 600 tons, so the curves to check are G and Q: `else: curve_set_list = ["G", "Q"]` + + - if the compressor type is CENTRIFUGAL: `if chiller["compressor_type"] == "CENTRIFUGAL":` + - if the capacity is less than 150 tons, the curves to check are H and R: `if rated_capacity < 150 tons: curve_set_list= ["H", "R"]` + - else if the capacity is less than 300 tons, the curves to check are H and S: `elif rated_capacity < 300 tons: curve_set_list = ["H", "S"]` + - else if the capacity is less than 400 tons, the curves to check are I and T: `elif rated_capacity < 400 tons: curve_set_list = ["I", "T"]` + - else if the capacity is less than 600 tons, the curves to check are J and U: `elif rated_capacity < 600 tons: curve_set_list = ["J", "U"]` + - else the capacity is greater than or equal to 600 tons, the curves to check are J and U: `else: curve_set_list = ["J", "U"]` + + - get the design temperature across the condenser: `design_temperature_across_condenser = chiller["design_leaving_condenser_temperature"] - chiller["design_entering_condenser_temperature"]` + + **Rule Assertion:** + - Case 1: all lists of missing or non-matching validation points have a length of zero and the design temperature across the condenser is 10F: PASS `if any(does_chiller_performance_match_curve(chiller, curve_set) for curve_set in curve_set_list) and design_temperature_across_condenser == 10: PASS` + - Case 2: all lists of missing or non-matching validation points have a length of zero and the design temperature across the condenser is NOT 10F: FAIL `elif any(does_chiller_performance_match_curve(chiller, curve_set) for curve_set in curve_set_list) and design_temperature_across_condenser != 10: FAIL` + - Case 3: else when the chiller performance does not match the curves in Appendix J: UNDETERMINED `else: UNDETERMINED and raise_message "FAIL unless manufacturer full- and part-load data is provided to support the modeled curves.` + - Note to RDS team - if there is missing operating point data the outcome is also UNDETERMINED with a message indicating that the modeled performance curves could not be evaluated. **Notes:** -1. Can we add chiller.design_leaving_condenser_temperature to the schema? Need to make public comment to add. -2. Update is_chiller_performance_app_j() to take in which table to reference? +1. This rule requires a new data element in the schema: 'design_leaving_condenser_temperature' in the Chiller data group **[Back](../_toc.md)**