From ce9e82bd03aa0d0e7534ae21dbcd3240c9721692 Mon Sep 17 00:00:00 2001 From: gonz102 Date: Wed, 11 Sep 2024 19:58:59 -0400 Subject: [PATCH 1/8] First cut at rule test 11-6 --- .../ashrae9012019/section11/rule_11_6.json | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 rct229/ruletest_engine/ruletest_jsons/ashrae9012019/section11/rule_11_6.json diff --git a/rct229/ruletest_engine/ruletest_jsons/ashrae9012019/section11/rule_11_6.json b/rct229/ruletest_engine/ruletest_jsons/ashrae9012019/section11/rule_11_6.json new file mode 100644 index 0000000000..868e155014 --- /dev/null +++ b/rct229/ruletest_engine/ruletest_jsons/ashrae9012019/section11/rule_11_6.json @@ -0,0 +1,131 @@ +{ + "rule-11-6-a": { + "Section": 11, + "Rule": 6, + "Test": "a", + "test_description": "A one story building, single zone building has service hot water piping. The service hot water piping losses are correctly modeled.", + "expected_rule_outcome": "pass", + "standard": { + "rule_id": "11-6", + "ruleset_reference": "Table G3.1 #11, baseline column, i", + "rule_description": "Piping losses shall not be modeled.", + "applicable_rmr": "Baseline Model", + "rule_assertion": "=", + "comparison_value": "Expected Value", + "mandatory_rule": "No", + "schema_version": "0.0.34" + }, + "rmd_transformations": { + "baseline": { + "id": "ASHRAE229 1", + "calendar": { + "is_leap_year": false + }, + "data_timestamp": "2024-02-12T12:00Z", + "ruleset_model_descriptions": [ + { + "id": "RMD 1", + "buildings": [ + { + "id": "Building 1", + "building_segments": [ + { + "id": "Building Segment 1", + "zones": [ + { + "id": "Thermal Zone 1", + "floor_name": "Floor1", + "spaces": [ + { + "id": "Space 1", + "floor_area": 929.0303999999999 + } + ] + } + ] + } + ] + } + ], + "service_water_heating_distribution_systems": [ + { + "id": "SHW 1", + "service_water_piping": [ + { + "id": "SHW Piping 1", + "are_thermal_losses_modeled": true + } + ] + } + ], + "type": "BASELINE_0" + } + ] + } + } + }, + "rule-11-6-b": { + "Section": 11, + "Rule": 6, + "Test": "b", + "test_description": "A one story building, single zone building has service hot water piping. The service hot water piping losses are not modeled.", + "expected_rule_outcome": "fail", + "standard": { + "rule_id": "11-6", + "ruleset_reference": "Table G3.1 #11, baseline column, i", + "rule_description": "Piping losses shall not be modeled.", + "applicable_rmr": "Baseline Model", + "rule_assertion": "=", + "comparison_value": "Expected Value", + "mandatory_rule": "No", + "schema_version": "0.0.34" + }, + "rmd_transformations": { + "baseline": { + "id": "ASHRAE229 1", + "calendar": { + "is_leap_year": false + }, + "data_timestamp": "2024-02-12T12:00Z", + "ruleset_model_descriptions": [ + { + "id": "RMD 1", + "buildings": [ + { + "id": "Building 1", + "building_segments": [ + { + "id": "Building Segment 1", + "zones": [ + { + "id": "Thermal Zone 1", + "floor_name": "Floor1", + "spaces": [ + { + "id": "Space 1" + } + ] + } + ] + } + ] + } + ], + "service_water_heating_distribution_systems": [ + { + "id": "SHW 1", + "service_water_piping": [ + { + "id": "SHW Piping 1", + "are_thermal_losses_modeled": false + } + ] + } + ], + "type": "BASELINE_0" + } + ] + } + } + } +} \ No newline at end of file From 05909eaa3bb4e3635a58c6579fd0c2ee2a61aff2 Mon Sep 17 00:00:00 2001 From: Juan Gonzalez Date: Thu, 12 Sep 2024 14:58:43 -0400 Subject: [PATCH 2/8] Update ASHRAE229.schema.json Indentation fix --- rct229/schema/ASHRAE229.schema.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rct229/schema/ASHRAE229.schema.json b/rct229/schema/ASHRAE229.schema.json index 2a9afb42dc..1a0e4ce12d 100644 --- a/rct229/schema/ASHRAE229.schema.json +++ b/rct229/schema/ASHRAE229.schema.json @@ -4226,7 +4226,7 @@ "description": "Indicates if service water heating piping is a loop and recirculates", "type": "boolean" }, - "are_thermal_losses_modeled": { + "are_thermal_losses_modeled": { "description": "Indicates if thermal losses from the service water heating piping are modeled", "type": "boolean" }, @@ -5084,4 +5084,4 @@ }, "version": "0.0.36", "$ref": "ASHRAE229.schema.json#/definitions/RulesetProjectDescription" -} \ No newline at end of file +} From d0132a82128c7033e2afac8df6fa8f42ea1c3456 Mon Sep 17 00:00:00 2001 From: gonz102 Date: Thu, 12 Sep 2024 15:24:37 -0400 Subject: [PATCH 3/8] Addressed issue where SHW distributions were not referenced by any space for 11-6 rule test --- .../ashrae9012019/section11/rule_11_6.json | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/rct229/ruletest_engine/ruletest_jsons/ashrae9012019/section11/rule_11_6.json b/rct229/ruletest_engine/ruletest_jsons/ashrae9012019/section11/rule_11_6.json index 868e155014..4e1e744db3 100644 --- a/rct229/ruletest_engine/ruletest_jsons/ashrae9012019/section11/rule_11_6.json +++ b/rct229/ruletest_engine/ruletest_jsons/ashrae9012019/section11/rule_11_6.json @@ -38,7 +38,12 @@ "spaces": [ { "id": "Space 1", - "floor_area": 929.0303999999999 + "service_water_heating_uses": [ + { + "id": "SHW 1", + "served_by_distribution_system": "SHW Distribution 1" + } + ] } ] } @@ -49,7 +54,7 @@ ], "service_water_heating_distribution_systems": [ { - "id": "SHW 1", + "id": "SHW Distribution 1", "service_water_piping": [ { "id": "SHW Piping 1", @@ -102,7 +107,13 @@ "floor_name": "Floor1", "spaces": [ { - "id": "Space 1" + "id": "Space 1", + "service_water_heating_uses": [ + { + "id": "SHW 1", + "served_by_distribution_system": "SHW Distribution 1" + } + ] } ] } @@ -113,7 +124,7 @@ ], "service_water_heating_distribution_systems": [ { - "id": "SHW 1", + "id": "SHW Distribution 1", "service_water_piping": [ { "id": "SHW Piping 1", From c29b727e81e5b33c6296524941d6bf60a3a03301 Mon Sep 17 00:00:00 2001 From: gonz102 Date: Wed, 18 Sep 2024 15:33:16 -0400 Subject: [PATCH 4/8] Flipped pass and fail cases for 11-6 ruletest --- .../ashrae9012019/section11/rule_11_6.json | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/rct229/ruletest_engine/ruletest_jsons/ashrae9012019/section11/rule_11_6.json b/rct229/ruletest_engine/ruletest_jsons/ashrae9012019/section11/rule_11_6.json index 4e1e744db3..a6faa0cab7 100644 --- a/rct229/ruletest_engine/ruletest_jsons/ashrae9012019/section11/rule_11_6.json +++ b/rct229/ruletest_engine/ruletest_jsons/ashrae9012019/section11/rule_11_6.json @@ -3,7 +3,7 @@ "Section": 11, "Rule": 6, "Test": "a", - "test_description": "A one story building, single zone building has service hot water piping. The service hot water piping losses are correctly modeled.", + "test_description": "A one story, single zone building has service hot water piping. The service hot water piping losses are correctly not modeled.", "expected_rule_outcome": "pass", "standard": { "rule_id": "11-6", @@ -12,7 +12,7 @@ "applicable_rmr": "Baseline Model", "rule_assertion": "=", "comparison_value": "Expected Value", - "mandatory_rule": "No", + "mandatory_rule": "Yes", "schema_version": "0.0.34" }, "rmd_transformations": { @@ -58,7 +58,7 @@ "service_water_piping": [ { "id": "SHW Piping 1", - "are_thermal_losses_modeled": true + "are_thermal_losses_modeled": false } ] } @@ -73,7 +73,7 @@ "Section": 11, "Rule": 6, "Test": "b", - "test_description": "A one story building, single zone building has service hot water piping. The service hot water piping losses are not modeled.", + "test_description": "A one story, single zone building has service hot water piping. The service hot water piping losses are modeled.", "expected_rule_outcome": "fail", "standard": { "rule_id": "11-6", @@ -82,7 +82,7 @@ "applicable_rmr": "Baseline Model", "rule_assertion": "=", "comparison_value": "Expected Value", - "mandatory_rule": "No", + "mandatory_rule": "Yes", "schema_version": "0.0.34" }, "rmd_transformations": { @@ -108,6 +108,7 @@ "spaces": [ { "id": "Space 1", + "service_water_heating_space_type": "OFFICE", "service_water_heating_uses": [ { "id": "SHW 1", @@ -128,7 +129,7 @@ "service_water_piping": [ { "id": "SHW Piping 1", - "are_thermal_losses_modeled": false + "are_thermal_losses_modeled": true } ] } From ac7ac40fceabb989c44061abae33ab1e8aa61278 Mon Sep 17 00:00:00 2001 From: yunjoonjung Date: Mon, 11 Nov 2024 22:01:28 -0800 Subject: [PATCH 5/8] Added 11-6 rule --- docs/section11/Rule11-6.md | 7 +- rct229/cli.py | 2 +- rct229/rulesets/ashrae9012019/__init__.py | 1 + .../ashrae9012019/section11/section11rule6.py | 93 +++++++++++++++++++ 4 files changed, 98 insertions(+), 5 deletions(-) create mode 100644 rct229/rulesets/ashrae9012019/section11/section11rule6.py diff --git a/docs/section11/Rule11-6.md b/docs/section11/Rule11-6.md index 9cd9c77a8d..3a565a8aef 100644 --- a/docs/section11/Rule11-6.md +++ b/docs/section11/Rule11-6.md @@ -3,14 +3,13 @@ **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 **Evaluation Context:** Each SWH Distribution System **Data Lookup:** **Function Call:** - 1. get_swh_components_associated_with_each_swh_distribution_system() **Applicability Checks:** @@ -20,13 +19,13 @@ ## Rule Logic: - use get_swh_components_associated_with_each_swh_distribution_system to get the SWH BATs and SWH equipment in the building: `swh_distribution_and_eq_dict = get_swh_components_associated_with_each_swh_distribution_system(B_RMD)` - create a value indicating whether piping losses were modeled: `piping_losses_modeled = false` - - look at every ServiceWaterPiping connected to the distribution: `for piping_id in swh_distribution_and_eq_dict[distribution_id]["Piping"]` + - look at every ServiceWaterPiping including child pipings connected to the distribution: `for piping_id in swh_distribution_and_eq_dict[distribution_id]["Piping"]` - get the piping: `piping = get_component_by_id(piping_id, B_RMD, ServiceWaterPiping) ` - check if the piping has piping_losses_modeled: `if piping.are_thermal_losses_modeled:` - 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` diff --git a/rct229/cli.py b/rct229/cli.py index 1814fff0f7..958cdc38e4 100644 --- a/rct229/cli.py +++ b/rct229/cli.py @@ -29,7 +29,7 @@ def cli(): Software test workflow, add sections to do test. \n --ruleset or -rs: default is ashrae9012019, available: ashrae9012019\n argument (optional): section string, \n - currently available: section1, section4, section5, section6, section10, section12, section16, section18, section19, section21, section22 and section23""" + currently available: section1, section4, section5, section6, section10, section11, section12, section16, section18, section19, section21, section22 and section23""" @cli.command( diff --git a/rct229/rulesets/ashrae9012019/__init__.py b/rct229/rulesets/ashrae9012019/__init__.py index 9cd0ff1f56..ca69f1048a 100644 --- a/rct229/rulesets/ashrae9012019/__init__.py +++ b/rct229/rulesets/ashrae9012019/__init__.py @@ -11,6 +11,7 @@ "section5", "section6", "section10", + "section11", "section12", "section16", "section18", diff --git a/rct229/rulesets/ashrae9012019/section11/section11rule6.py b/rct229/rulesets/ashrae9012019/section11/section11rule6.py new file mode 100644 index 0000000000..29ab4827c7 --- /dev/null +++ b/rct229/rulesets/ashrae9012019/section11/section11rule6.py @@ -0,0 +1,93 @@ +from collections import deque + +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_equipment_associated_with_each_swh_distriubtion_system import ( + get_swh_equipment_associated_with_each_swh_distribution_system, +) +from rct229.utils.jsonpath_utils import find_all + + +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.SWHDistRule(), + index_rmd=BASELINE_0, + list_path="$.service_water_heating_distribution_systems[*]", + ) + + def is_applicable(self, context, data=None): + rmd_b = context.BASELINE_0 + + swh_dist_sys_b = find_all( + "$.service_water_heating_distribution_systems[*]", rmd_b + ) + + return swh_dist_sys_b + + def create_data(self, context, data): + rmd_b = context.BASELINE_0 + + swh_distribution_and_eq_list_b = ( + get_swh_equipment_associated_with_each_swh_distribution_system(rmd_b) + ) + + return {"swh_distribution_and_eq_list_b": swh_distribution_and_eq_list_b} + + class SWHDistRule(RuleDefinitionBase): + def __init__(self): + super(Section11Rule6.RMDRule.SWHDistRule, self).__init__( + rmds_used=produce_ruleset_model_description( + USER=False, + BASELINE_0=True, + PROPOSED=False, + ), + required_fields={ + "$": ["service_water_piping"], + }, + ) + + def get_calc_vals(self, context, data=None): + swh_dist_sys_b = context.BASELINE_0 + + piping_losses_modeled_b = [] + for service_water_piping in swh_dist_sys_b["service_water_piping"]: + queue = deque([service_water_piping]) + while queue: + current_piping = queue.popleft() + children_piping = current_piping.get("child", []) + queue.extend(children_piping) + + piping_losses_modeled_b.append( + current_piping.get("are_thermal_losses_modeled") + ) + + 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 any(piping_losses_modeled_b) From 9791f3a878d3a1ecc93bc89e9001231fb51aae0c Mon Sep 17 00:00:00 2001 From: yunjoonjung Date: Mon, 11 Nov 2024 22:02:40 -0800 Subject: [PATCH 6/8] Added init file --- .../ashrae9012019/section11/__init__.py | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 rct229/rulesets/ashrae9012019/section11/__init__.py diff --git a/rct229/rulesets/ashrae9012019/section11/__init__.py b/rct229/rulesets/ashrae9012019/section11/__init__.py new file mode 100644 index 0000000000..439d820dc4 --- /dev/null +++ b/rct229/rulesets/ashrae9012019/section11/__init__.py @@ -0,0 +1,32 @@ +# Add all available rule modules in __all__ +import importlib + +__all__ = [ + # "section11rule1", + # "section11rule2", + # "section11rule3", + # "section11rule4", + # "section11rule5", + "section11rule6", + # "section11rule7", + # "section11rule8", + # "section11rule9", + # "section11rule10", + # "section11rule11", + # "section11rule12", + # "section11rule13", + # "section11rule14", + # "section11rule15", + # "section11rule16", + # "section11rule17", +] + + +def __getattr__(name): + if name in __all__: + return importlib.import_module("." + name, __name__) + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") + + +def __dir__(): + return sorted(__all__) From 64c111ab87b8d5c477af1a9e293024f254296d2d Mon Sep 17 00:00:00 2001 From: yunjoonjung Date: Tue, 12 Nov 2024 13:41:26 -0800 Subject: [PATCH 7/8] Updated var name --- rct229/rulesets/ashrae9012019/section11/section11rule6.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rct229/rulesets/ashrae9012019/section11/section11rule6.py b/rct229/rulesets/ashrae9012019/section11/section11rule6.py index 29ab4827c7..64f7b1644b 100644 --- a/rct229/rulesets/ashrae9012019/section11/section11rule6.py +++ b/rct229/rulesets/ashrae9012019/section11/section11rule6.py @@ -42,11 +42,11 @@ def __init__(self): def is_applicable(self, context, data=None): rmd_b = context.BASELINE_0 - swh_dist_sys_b = find_all( + swh_dist_sys_list_b = find_all( "$.service_water_heating_distribution_systems[*]", rmd_b ) - return swh_dist_sys_b + return swh_dist_sys_list_b def create_data(self, context, data): rmd_b = context.BASELINE_0 From 63b3ad664ef6e24865a6a0baefe671556b766e05 Mon Sep 17 00:00:00 2001 From: yunjoonjung Date: Sun, 1 Dec 2024 22:50:41 -0800 Subject: [PATCH 8/8] Updated 11-6 --- docs/section11/Rule11-6.md | 34 +++++++++++-------- .../ashrae9012019/section11/section11rule6.py | 12 ------- 2 files changed, 19 insertions(+), 27 deletions(-) diff --git a/docs/section11/Rule11-6.md b/docs/section11/Rule11-6.md index 3a565a8aef..0e449e3e67 100644 --- a/docs/section11/Rule11-6.md +++ b/docs/section11/Rule11-6.md @@ -5,28 +5,32 @@ **Rule ID:** 11-6 **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 +**Appendix G Section Reference:** Table G3.1 #11, baseline column, i **Evaluation Context:** Each SWH Distribution System -**Data Lookup:** -**Function Call:** -1. get_swh_components_associated_with_each_swh_distribution_system() +**Data Lookup:** +**Function Call:** **Applicability Checks:** -- Every Baseline distribution system is applicable +- Every Baseline distribution system is applicable - ## Rule Logic: -- use get_swh_components_associated_with_each_swh_distribution_system to get the SWH BATs and SWH equipment in the building: `swh_distribution_and_eq_dict = get_swh_components_associated_with_each_swh_distribution_system(B_RMD)` - - create a value indicating whether piping losses were modeled: `piping_losses_modeled = false` - - look at every ServiceWaterPiping including child pipings connected to the distribution: `for piping_id in swh_distribution_and_eq_dict[distribution_id]["Piping"]` - - get the piping: `piping = get_component_by_id(piping_id, B_RMD, ServiceWaterPiping) ` - - check if the piping has piping_losses_modeled: `if piping.are_thermal_losses_modeled:` - - set the piping_losses_modeled to true and go directly to rule assertion: `piping_losses_modeled = true: GO TO RULE_ASSERTION` +## Rule Logic: +- Get to the `service_water_heating_distribution_systems` level + - Define a list that stores the pipe data: `piping_losses_modeled = []` + - Loop over the `service_water_piping` object: `for service_water_piping in swh_dist_sys_b["service_water_piping"]:` + - Store the current piping obj: `queue = deque([service_water_piping])` + - Check the `are_thermal_losses_modeled` value including all the child pipes: + - `while queue:` + - `current_piping = queue.popleft()` + - `children_piping = current_piping.get("child", [])` + - `queue.extend(children_piping)` + - `piping_losses_modeled_b.append(current_piping.get("are_thermal_losses_modeled"))` - - **Rule Assertion - Zone:** - - Case1: piping losses are not modeled, PASS: `if piping_losses_modeled == False: PASS` - - Case2: piping losses are modeled, FAIL: `else: FAIL` + +- **Rule Assertion - Zone:** +- Case1: piping losses are not modeled, PASS: `if not any(piping_losses_modeled_b): PASS` +- Case2: piping losses are modeled, FAIL: `else: FAIL` **Notes:** diff --git a/rct229/rulesets/ashrae9012019/section11/section11rule6.py b/rct229/rulesets/ashrae9012019/section11/section11rule6.py index 64f7b1644b..0808fc058b 100644 --- a/rct229/rulesets/ashrae9012019/section11/section11rule6.py +++ b/rct229/rulesets/ashrae9012019/section11/section11rule6.py @@ -4,9 +4,6 @@ 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_equipment_associated_with_each_swh_distriubtion_system import ( - get_swh_equipment_associated_with_each_swh_distribution_system, -) from rct229.utils.jsonpath_utils import find_all @@ -48,15 +45,6 @@ def is_applicable(self, context, data=None): return swh_dist_sys_list_b - def create_data(self, context, data): - rmd_b = context.BASELINE_0 - - swh_distribution_and_eq_list_b = ( - get_swh_equipment_associated_with_each_swh_distribution_system(rmd_b) - ) - - return {"swh_distribution_and_eq_list_b": swh_distribution_and_eq_list_b} - class SWHDistRule(RuleDefinitionBase): def __init__(self): super(Section11Rule6.RMDRule.SWHDistRule, self).__init__(