Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/pnnl/ruleset-checking-tool
Browse files Browse the repository at this point in the history
… into RS/WX/rule1-9
  • Loading branch information
weilixu committed Feb 27, 2025
2 parents 3bab470 + e577283 commit 54df8c0
Show file tree
Hide file tree
Showing 473 changed files with 644,580 additions and 257,186 deletions.
34 changes: 34 additions & 0 deletions .github/workflows/auto-feature-pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Auto PR from develop branch to a feature branch

on:
pull_request:
types:
- closed
branches:
- develop

env:
TARGET_BRANCH: feature/ashrae-9012022 #define the target branch when in parallel developing a feature

jobs:
create-pr:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.AUTO_PAT }}

- name: Create Pull Request from develop to feature/ashrae-9012022
uses: peter-evans/create-pull-request@v4
with:
base: feature/ashrae-9012022
branch: develop
title: "Merge develop into feature/update_tool"
body: "This PR merges the latest chagens from the develop branch into the feature/ashrae-9012022 branch"
reviewers: weilixu
draft: false
labels: "auto-pr"
token: ${{ secrets.AUTO_PAT }}
1 change: 1 addition & 0 deletions docs/_toc.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ These conventions are used in all RDS below, and the logic of evaluating rules f
*[1-3](section1/Rule1-3.md): The Performance Cost Index-Target (PCIt) shall be calculated using the procedures defined in Section 4.2.1.1. The PCIt shall be equal to [baseline building unregulated energy cost (BBUEC) + BPF x baseline building regulated energy cost (BBREC)]/ BBP
*[1-4](section1/Rule1-4.md): The PCI shall be less than or equal to the PCIt when calculated in accordance with Standard 90.1 2019, Section 4.2.1.1.
*[1-5](section1/Rule1-5.md): When on-site renewable energy generation exceeds the thresholds defined in Section 4.2.1.1, the methodology defined in this section shall be used to calculate the PCIt.
*[1-6](section1/Rule1-6.md): On-site renewable energy shall not be included in the baseline building performance.

## Section 3 - Space Use Classification

Expand Down
38 changes: 38 additions & 0 deletions docs/section1/Rule1-6.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@

# Section 1 - Rule 1-6

**Rule ID:** 1-6
**Rule Description:** On-site renewable energy shall not be included in the baseline building performance.
**Rule Assertion:** Baseline RMD = expected value
**Appendix G Section:** G3.11 18 Baseline

**Mandatory Rule:** True
**Evaluation Context:** Each baseline RMD
**Function Call:**

## Applicability Check:
- All projects are applicable


## Rule Logic:
- set a boolean has_renewables and set it to false: `has_renewables = false`
- look at each baseline model rotation: `for rotation in [B_RMD, B_RMD_90, B_RMD_180, B_RMD_270]:`
- get the baseline output schema: `output = rotation.output`
- get the output instance: `output_instance = output.output_instance`
- look at each end use result: `for end_use_result in output_instance.annual_end_use_results:`
- check if the energy source for the end_use_result is "ON_SITE_RENEWABLES": `if end_use_result.energy_source == "ON_SITE_RENEWABLES":`
- check if the energy end use is greater than 0: `if end_us_result.annual_site_energy_use > 0:`
- set has_renewables to true and continue to rule assertion: `has_renewables = true; CONTINUE TO RULE ASSERTION`
- if we get here without going to the rule assertion, continue to rule assertion: `CONTINUE TO RULE ASSERTION`

**Rule Assertion:**
- Case 1: If has_renewables is true, then FAIL: `if has_renewables == true: FAIL`
- Case 2: otherwise, there are no renewables, PASS: `else: PASS`


**Notes:**
1.

**[Back](../_toc.md)**


4 changes: 2 additions & 2 deletions docs/section12/Rule12-2.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ find_exactly_one_schedule, find_all, compare_schedules
- Get the corresponding miscellaneous equipment load from the proposed RMD: `misc_equip_p = match_data_element(P_RMD, MiscellaneousEquipment, misc_equip_b.id)`
- Get the baseline miscellaneous equipment load schedule: `misc_equip_schedule_b = misc_equip_b.multiplier_schedule`
- Get the proposed miscellaneous equipment load schedule: `misc_equip_schedule_p = misc_equip_p.multiplier_schedule`
- Get the baseline automatic receptacle control: `auto_receptacle_control_b = misc_equip_b.has_automatic_control`
- Get the proposed automatic receptacle control: `auto_receptacle_control_p = misc_equip_p.has_automatic_control`
- Get the baseline automatic receptacle control: `auto_receptacle_control_b = misc_equip_b.automatic_controlled_percentage > 0.0`
- Get the proposed automatic receptacle control: `auto_receptacle_control_p = misc_equip_p.automatic_controlled_percentage > 0.0`
- If it is a leap year, set the schedule comparison mask to 8784 hours, else set it to 8760 hours: `mask_schedule = [1] * 8784 if is_leap_year else [1] * 8760`
- Compare the baseline miscellaneous equipment load schedule to the proposed miscellaneous equipment load schedule: `comparison_data = compare_schedules(misc_equip_schedule_b, misc_equip_schedule_p, mask_schedule)`

Expand Down
4 changes: 2 additions & 2 deletions docs/section12/Rule12-3.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
- Iterate through the spaces in the proposed model: `for space_p in P_RMD...spaces`
- Get the lighting space type: `space_type_p = space_p.lighting_space_type`
- Iterate through the miscellaneous equipment loads in the space: `for misc_equip_p in space_p.miscellaneous_equipment:`
- Get the proposed automatic receptacle control: `auto_receptacle_control_p = misc_equip_p.has_automatic_control`
- Get the proposed automatic receptacle control: `auto_receptacle_control_p = misc_equip_p.automatic_controlled_percentage > 0.0 `
- If the space type is not in the list of space types where receptacle controls may be required, and the space has automatic receptacle controls installed: `if space_type_p not in EXPECTED_RECEPTACLE_CONTROL_SPACE_TYPES and auto_receptacle_control_p:`
- Add the space to the list of spaces with receptacle controls installed where not required: `spaces_with_receptacle_controls_beyond_req.append(space_p.id)`
- Rule is applicable if the list of spaces with receptacle controls installed where not required is not empty: `applicable = len(spaces_with_receptacle_controls_beyond_req) > 0`
Expand All @@ -33,7 +33,7 @@
- Iterate through the spaces in the proposed model: `for space_p in P_RMD...spaces`
- Get the lighting space type: `space_type_p = space_p.lighting_space_type`
- Iterate through the miscellaneous equipment loads in the space: `for misc_equip_p in space_p.miscellaneous_equipment:`
- Get the proposed automatic receptacle control: `auto_receptacle_control_p = misc_equip_p.has_automatic_control`
- Get the proposed automatic receptacle control: `auto_receptacle_control_p = misc_equip_p.automatic_controlled_percentage > 0.0 `
- If the space type is not in the list of space types where receptacle controls may be required, and the space has automatic receptacle controls installed: `if space_type_p not in EXPECTED_RECEPTACLE_CONTROL_SPACE_TYPES and auto_receptacle_control_p:`
- Get the percentage of controlled receptacles: `controlled_percentage = misc_equip_p.automatic_controlled_percentage`
- Calculate the expected receptacle power credit: `expected_receptacle_power_credit = 0.10 * controlled_percentage`
Expand Down
11 changes: 8 additions & 3 deletions docs/section21/Rule21-17.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,19 @@
## Rule Logic:

- For each boiler in B-RMR: `for boiler_b in B_RMR.RulesetModelInstance.boilers:`
- Get boiler efficiency metric types: `boiler_efficiency_metric_types_b = boiler_b.efficiency_metric_types`
- Get boiler efficiency metric values: `boiler_efficiency_metric_values_b = boiler_b.efficiency_values_types`
- Get AFUE if present: `boiler_annual_fuel_utilization_efficiency_b = next((value for metric, value in zip(boiler_efficiency_metric_types_b, boiler_efficiency_metric_values_b,)if metric == "ANNUAL_FUEL_UTILIZATION"), None,)`
- Get thermal efficiency if present: `boiler_thermal_efficiency_b = next((value for metric, value in zip(boiler_efficiency_metric_types_b, boiler_efficiency_metric_values_b,)if metric == "THERMAL"), None,)`
- Get combustion efficiency if present: `boiler_combustion_efficiency_b = next((value for metric, value in zip(boiler_efficiency_metric_types_b, boiler_efficiency_metric_values_b,)if metric == "COMBUSTION"), None,)`

**Rule Assertion - Component:**

- Case 1: For each boiler, if its rated capacity is less than 300,000Btuh, and its efficiency metric is AFUE, and its efficiency is 80%: `if ( boiler_b.rated_capacity < 300000 ) AND ( boiler_b.efficiency_metric == "ANNUAL_FUEL_UTILIZATION" ) AND ( boiler_b.efficiency == 0.8 ): PASS`
- Case 1: For each boiler, if its rated capacity is less than 300,000Btuh, and its efficiency metric is AFUE, and its efficiency is 80%: `if ( boiler_b.rated_capacity < 300000 ) AND ( boiler_annual_fuel_utilization_efficiency_b ) AND ( boiler_annual_fuel_utilization_efficiency_b == 0.8 ): PASS`

- Case 2: Else if its rated capacity is less than or equal to 2,500,000Btuh, and its efficiency metric is thermal, and its efficiency is 75%: `if ( boiler_b.rated_capacity <= 2500000 ) AND ( boiler_b.efficiency_metric == "THERMAL" ) AND ( boiler_b.efficiency == 0.75 ): PASS`
- Case 2: Else if its rated capacity is less than or equal to 2,500,000Btuh, and its efficiency metric is thermal, and its efficiency is 75%: `if ( boiler_b.rated_capacity <= 2500000 ) AND ( boiler_thermal_efficiency_b ) AND ( boiler_thermal_efficiency_b == 0.75 ): PASS`

- Case 3: Else if its rated capacity is more than 2,500,000Btuh, and its efficiency metric is combustion, and its efficiency is 80%: `if ( boiler_b.rated_capacity > 2500000 ) AND ( boiler_b.efficiency_metric == "COMBUSTION" ) AND ( boiler_b.efficiency == 0.8 ): PASS`
- Case 3: Else if its rated capacity is more than 2,500,000Btuh, and its efficiency metric is combustion, and its efficiency is 80%: `if ( boiler_b.rated_capacity > 2500000 ) AND ( boiler_combustion_efficiency_b ) AND ( boiler_combustion_efficiency_b == 0.8 ): PASS`

- Case 4: Else: `else: FAIL`

Expand Down
2 changes: 1 addition & 1 deletion docs/section22/Rule22-19.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

**Rule Assertion:**

- Case 1: If condensing loop temperature reset type is constant: `if loop_b.cooling_or_condensing_design_and_control.temperature_reset_type == "CONSTANT": PASS`
- Case 1: If condensing loop temperature reset type is constant: `if loop_b.cooling_or_condensing_design_and_control.temperature_reset_type == "NO_RESET": PASS`

- Case 2: Else: `else: FAIL`

Expand Down
10 changes: 8 additions & 2 deletions docs/section22/Rule22-22.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,20 @@
- For each chiller in B_RMR: `for chiller_b in B_RMR.RulesetModelInstance.chillers:`

- Get chiller rated capacity: `rated_capacity_b = chiller_b.rated_capacity`

- Get chiller rate capacity: `size_category_b = chiller_b.rated_capacity`

- Get chiller efficiency metric types: `efficiency_metric_types_b = chiller_b.efficiency_metric_types`

- Get chiller efficiency metric values: `efficiency_metric_values_b = chiller_b.efficiency_metric_values`

- Check if "FULL_LOAD_EFFICIENCY_DESIGN" is in chiller efficiency metric types and get the corresponding chiller part load efficiency: ` chiller_full_load_efficiency = next((value for metric, value in zip(efficiency_metric_types_b, efficiency_metric_values_b)if metric == FULL_LOAD_EFFICIENCY), None,)`

- Get baseline chiller efficiency requirements: `kW_ton_full_load_b = data_lookup(table_G3_5_3, chiller_b.compressor_type, size_category_b, "FL")`

**Rule Assertion - Component:**

- Case 1: For each chiller, if chiller full-load efficiency is modeled at the minimum efficiency levels in accordance with Tables G3.5.3 `if chiller_b.full_load_efficiency == kW_ton_full_load_b * CONVERSION(KW_PER_TON_TO_COP): PASS`
- Case 1: For each chiller, if chiller full-load efficiency is modeled at the minimum efficiency levels in accordance with Tables G3.5.3 `if chiller_full_load_efficiency == kW_ton_full_load_b * CONVERSION(KW_PER_TON_TO_COP): PASS`

- Case 2: Else: `else: FAIL`

Expand Down
2 changes: 1 addition & 1 deletion docs/section22/Rule22-32.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
- For each chiller in B_RMR: `for chiller_b in B_RMR.RulesetModelInstance.chillers:`

- Get chiller rated capacity: `rated_capacity_b = chiller_b.rated_capacity`

- Get chiller part load efficiency `chiller_part_load_efficiency = chiller_b.rated_capacity`
- Get baseline chiller efficiency requirements: `kW_ton_part_load_b = data_lookup(table_G3_5_3, chiller_b.compressor_type, size_category, "IPLV")`

**Rule Assertion - Component:**
Expand Down
11 changes: 5 additions & 6 deletions examples/baseline_rmd.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"id": "ashrae_229_1",
"weather": {
"climate_zone": "CZ4A",
"data_source_type": "HISTORIC_AGGREGATION"
},
"ruleset_model_descriptions": [
{"id": "987",
"weather": {
"climate_zone": "CZ4A",
"data_source_type": "HISTORIC_AGGREGATION"
},
"buildings": [
{
"id": "0",
Expand Down Expand Up @@ -148,6 +148,5 @@
],
"type": "BASELINE_0"
}
],
"data_timestamp": "2024-02-12T09:00Z"
]
}
77 changes: 73 additions & 4 deletions examples/chicago_demo/baseline_model.json
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,17 @@
}
],
"ventilation_space_type": "OFFICE_BUILDINGS_OFFICE_SPACE",
"service_water_heating_space_type": "OFFICE"
"service_water_heating_space_type": "OFFICE",
"service_water_heating_uses": [
{
"id": "SHW 1",
"served_by_distribution_system": "SHW Distribution 1",
"use": 5000,
"use_units": "POWER",
"use_multiplier_schedule": "ALWAYS ON DISCRETE",
"temperature_at_fixture": 54.44444444444446
}
]
}
]
},
Expand Down Expand Up @@ -612,7 +622,17 @@
}
],
"ventilation_space_type": "OFFICE_BUILDINGS_OFFICE_SPACE",
"service_water_heating_space_type": "OFFICE"
"service_water_heating_space_type": "OFFICE",
"service_water_heating_uses": [
{
"id": "SHW 2",
"served_by_distribution_system": "SHW Distribution 1",
"use": 5000,
"use_units": "POWER",
"use_multiplier_schedule": "ALWAYS ON DISCRETE",
"temperature_at_fixture": 54.44444444444446
}
]
}
]
},
Expand Down Expand Up @@ -852,7 +872,17 @@
}
],
"ventilation_space_type": "OFFICE_BUILDINGS_OFFICE_SPACE",
"service_water_heating_space_type": "OFFICE"
"service_water_heating_space_type": "OFFICE",
"service_water_heating_uses": [
{
"id": "SHW 3",
"served_by_distribution_system": "SHW Distribution 1",
"use": 5000,
"use_units": "POWER",
"use_multiplier_schedule": "ALWAYS ON DISCRETE",
"temperature_at_fixture": 54.44444444444446
}
]
}
]
},
Expand Down Expand Up @@ -5263,6 +5293,11 @@
"id": "Secondary CHW Pump",
"loop_or_piping": "Secondary CHW Loop 1",
"speed_control": "VARIABLE_SPEED"
},
{
"id": "SHW Pump 1",
"loop_or_piping": "SHW Piping 1",
"design_electric_power": 100
}
],
"fluid_loops": [
Expand Down Expand Up @@ -102265,7 +102300,41 @@
"baseline_building_performance_energy_cost": 253345.21,
"baseline_building_unregulated_energy_cost": 14453.34,
"baseline_building_regulated_energy_cost": 334178.98
}
},
"service_water_heating_equipment": [
{
"id": "SHW Equipment 1",
"distribution_system": "SHW Distribution 1",
"heater_fuel_type": "NATURAL_GAS",
"heater_type": "CONVENTIONAL",
"input_power": 29307.111111111113,
"first_hour_rating": 189.25000000000003,
"efficiency_metric_types": [
"UNIFORM_ENERGY_FACTOR"
],
"efficiency_metric_values": [
0.4162
],
"tank": {
"id": "SHW Tank",
"type": "COMMERCIAL_STORAGE",
"storage_capacity": 378.50000000000006
}
}
],
"service_water_heating_distribution_systems": [
{
"id": "SHW Distribution 1",
"drain_heat_recovery_efficiency": 0.5,
"service_water_piping": [
{
"id": "SHW Piping 1",
"are_thermal_losses_modeled": false,
"is_recirculation_loop": true
}
]
}
]
}
],
"weather": {
Expand Down
Loading

0 comments on commit 54df8c0

Please sign in to comment.