From 83afcdd88997edfa97687925b3489adce4e20b2d Mon Sep 17 00:00:00 2001 From: KarenWGard <114143532+KarenWGard@users.noreply.github.com> Date: Thu, 5 Sep 2024 16:18:52 -0400 Subject: [PATCH 1/8] Create Rule22-42.md --- docs/section22/Rule22-42.md | 98 +++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 docs/section22/Rule22-42.md diff --git a/docs/section22/Rule22-42.md b/docs/section22/Rule22-42.md new file mode 100644 index 0000000000..bd6c485df0 --- /dev/null +++ b/docs/section22/Rule22-42.md @@ -0,0 +1,98 @@ + +# CHW & CW - Rule 22-42 + +**Rule ID:** 22-42 +**Rule Description:** The sets of performance curves specified in Table J-2 should be used to represent part-load performance of chillers in the baseline building design. +**Rule Assertion:** Baseline RMD = expected value +**Appendix G Section:** G3.2.2.1 Baseline + +**Mandatory Rule:** True +**Evaluation Context:** Each Chiller +**Table Lookup:** +J-6 +**Function Call:** + +## Applicability Check: +- look at each chiller - only water-cooled chillers are applicable (ie chillers with a condensing_loop): `for chiller in B_RMD.chillers:` + - if the chiller has a condensing_loop, and the chiller energy source is electricity, continue to rule logic: `if chiller.consensing_loop != NULL and chiller.energy_source_type == "ELECTRICITY": CONTINUE TO 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` + - convert the chiller rated capacity from watts to tons: `chiller_capacity_tons = rated_capacity * 0.000284345` + - check if the compressor type is CENTRIFUGAL: `if chiller.compressor_type == "CENTRIFUGAL":` + - if the capacity is less than 150 tons, the category is V: `if chiller_capacity_tons < 150: curve_set = "V"` + - else if the capacity is greater than or equal to 300 tons, the category is Y: `elif chiller_capacity_tons >= 300: curve_set = "Y"` + - otherwise, the capacity is between 150 and 300, so the curves set is X: `else: curve_set = "X"` + - otherwise, check if the compressor type is POSITIVE_DISPLACEMENT or SCROLL: `if chiller.compressor_type in ["POSITIVE_DISPLACEMENT","SCROLL"]:` + - if the capacity is less than 150 tons, the category is Z: `if chiller_capacity_tons < 150: curve_set = "Z"` + - else if the capacity is greater than or equal to 300 tons, the category is AA: `elif chiller_capacity_tons >= 300: curve_set = "AA"` + - otherwise, the capacity is between 150 and 300, so the curves set is AB: `else: curve_set = "AB"` + - continue if the curve set is not "NONE" - the curve set could be none if the chiller.compressor_type is not one of the recognized types for Appendix G: `if curve_set <> "NONE":` + - calculate the chiller rated power by dividing the chiller rated capacity by the chiller full load efficiency (cop): `rated_power = chiller.rated_capacity / chiller.full_load_efficiency` + - create a list of the expected capacity validation points - this is in 25% intervals, starting with 0.25 to 1: `expected_validation_plr = [0.25,0.5,0.75,1]` + - create a list of the expected temperatures for the chilled water temperature for the validation calculations - expected_chwt_temps - units are (F). The values are selected to capture the minimum, maximum, rating condition and some points in between: `expected_cwt_temps = [39,45,50,55]` + - create a list of the expected entering condenser temperatures for the condenser water temperature for the validation calculations - expected_ect_temps - units are (F). The values are selected to capture the minimum, maximum, rating condition and some points in between: `expected_ect_temps = [60,104,85,72.5,97.5]` + + - get the coefficients for the EIR-f-T curve (IP units) using a table lookup for table J-6. This assumes that the lookup function will return a list with the coefficients in order (C1,C2,...): `eir_f_t_coefficients = table_J_2_lookup(curve_set,"EIR-f-T")` + - get the coefficients for the CAP-f-T curve (IP units) using a table lookup for table J-6. This assumes that the lookup function will return a list with the coefficients in order (C1,C2,...): `cap_f_t_coefficients = table_J_2_lookup(curve_set,"Cap-f-T")` + - get the coefficients for the PLR curve (IP units) using a table lookup for table J-6. This assumes that the lookup function will return a list with the coefficients in order (C1,C2,...): `plr_coefficients = table_J_2_lookup(curve_set,"EIR-f-PLR")` + + - create a variable (capacity_validation_status) to track whether the capacity validation passes and set it to "PASS" - if the capacity validation fails at any point, this variable will change to give the values at which the capacity validation failed: `capacity_validation_status = "PASS"` + - create a variable (power_validation_status) to track whether the power validation passes and set it to "PASS" - if the power validation fails at any point, this variable will change to give the values at which teh power validation failed: `power_validation_status = "PASS" + + - convert the chiller.capacity_validation_points to a dictionary with the keys being a list of two values - [chilled_water_supply_temperature, condenser_temperature], and values being the capacity_validation_point itself. Sorting the validation points will allow the calculations that follow to be much simpler. Start by creating a dict capacity_validation_pts_dict: `capacity_validation_pts_dict = {}` + - look at each value in chiller.capacity_validation_points: `for capacity_validation_point in chiller.capacity_validation_points:` + - add the point to capacity_validation_pts_dict: `capacity_validation_pts_dict[[capacity_validation_point.chilled_water_supply_temperature, capacity_validation_point.condenser_temperature]] = capacity_validation_point` + + - do the same conversion with the chiller.power_validation_points and storing the results in power_validation_pts_dict. However in this case, the values are a list of points because we expect different loads at each point: `power_validation_pts_dict = {}` + - look at each value in chiller.power_validation_points: `for power_validation_point in chiller.power_validation_points:` + - set the default to a blank list: `power_validation_pts_dict.setdefault([[power_validation_point.chilled_water_supply_temperature, power_validation_point.condenser_temperature]], [])` + - append the power validation point to the list at this given: `power_validation_pts_dict[[power_validation_point.chilled_water_supply_temperature, power_validation_point.condenser_temperature]].append(power_validation_point)` + + - create a dictionary of the expected capacities for use in the power validation check: `given_capacities = {}` + - the following lines or logic do the capacity validation check: + - loop through the expected_cwt_temps: `for cwt in expected_cwt_temps:` + - loop through each expected_ect_temps: `for ect in expected_ect_temps:` + - look for the capacity validation point in capacity_validation_pts_dict: `if capacity_validation_pts_dict[[cwt, ect]]:` + - calculate the expected capacity by multiplying the result of the formula by the rated_capacity: `expected_capacity = (cap_f_t_coefficients[0] + cap_f_t_coefficients[1] * cwt + cap_f_t_coefficients[2] * cwt^2 + cap_f_t_coefficients[3] * ect + cap_f_t_coefficients[4] * ect^2 + cap_f_t_coefficients[5] * cwt * ect) * rated_capacity` + - get the given capacity: `given_capacity = capacity_validation_pts_dict[[cwt, ect]].result` + - if the expected capacity matches the given capacity, add the expected capacity to the expected_capacities dictionary. This should not be an exact match, but with a margin of error (see notes at the bottom for suggested margins of errors): `if expected_capacity == given_capacity: given_capacities[[cwt,ect]] = given_capacity` + - otherwise, if the expected capacity doesn't match the given capacity, then change capacity_validation_status and go to Rule Assertion: `else: capacity_validation_status = "Expected capacity does not match given capacity at CHWT: " + cwt + " & ECT: " + ect; GO TO RULE ASSERTION` + - otherwise this value doesn't exist, set the capacity_validation_status and go to rule assertion: `else: capacity_validation_status = "Required capacity validation point is missing. Expected CHWT: " + cwt + ", expected ECT: " + ect; GO TO RULE ASSERTION` + + - the following lines or logic do the power validation check: + - loop through the expected_cwt_temps: `for cwt in expected_cwt_temps:` + - loop through each expected_ect_temps: `for ect in expected_ect_temps:` + - look for the power validation points in power_validation_pts_dict: `if power_validation_pts_dict[[cwt, ect]]:` + - we are expecting to see multiple validation points aligning with the expected_validation_plr. Create a list of part load ratios that are given. Later we'll compare this with the expected list to make sure that all points are given: `given_plrs = []` + - look at each power validation point in the list: `for power_validation_point in power_validation_pts_dict[[cwt, ect]]:` + - get the load: `load = power_validation_point.load` + - get the given power: `given_power = power_validation_point.result` + - calculate the PLR by dividing the load by the given capacity at these operating conditions: `plr = load / given_capacities[[cwt, ect]]` + - check whether the plr is one of the plrs that we need to check: `if plr in expected_validation_plr:` + - add the plr to the list of plrs provided: `given_plrs.append(plr)` + - calculate eir_plr using the coefficients given: `eir_plr = plr_coefficients[0] + plr_coefficients[1] * plr + plr_coefficients[2] * plr^2` + - calculate the eir_ft using the coefficients given: `eir_ft = eir_f_t_coefficients[0] + eir_f_t_coefficients[1] * cwt + eir_f_t_coefficients[2] * cwt^2 + eir_f_t_coefficients[3] * ect + eir_f_t_coefficients[4] * ect^2 + eir_f_t_coefficients[5] * cwt * ect + - calculate the expected power using the formula: + - Chiller operating power = Rated Capacity × CAP-f-T × EIR-f-T × EIR-f-PLR × Chiller Input Power at Rated Conditions/Chiller Capacity at Rated Conditions + - in this case, the given capacity under these operating conditions is the rated capacity * cap_ft, so the modified formula is: + - Chiller operating power = given_capacity[[cwt, ect]] × EIR-f-T × EIR-f-PLR × Chiller Input Power at Rated Conditions/Chiller Capacity at Rated Conditions + + - `expected_power = given_capacity[[cwt, ect]] * eir_ft * eir_plr * rated_power/rated_capacity` + - check whether the expected power and the given power are equal. This should not be an exact match, but with a margin of error (see notes at the bottom for suggested margins of errors). If the expected power and given power do not match, update power_validation_status and GO TO RULE ASSERTION: `if expected_power != given_power: power_validation_status = "Expected power does not match given power at CHWT: " + cwt + ", ECT: " + ect + " & " + plr".; GO TO RULE ASSERTION` + - make sure that all of the expected plrs are covered by + + **Rule Assertion:** + - Case 1: both power_validation_status and capacity_validation_status are PASS: PASS: `if power_validation_status == capacity_validation_status == "PASS"; PASS` + - Case 2: capacity validation status is not PASS, return fail and raise warning with the capacity_validation_status as an additional message: `if capacity_validation_status != "PASS": FAIL; raise_warning: capacity_validation_status` + - Case 3: power validation status is not PASS, return fail and raise warning with the power_validation_status as an additional message: `if power_validation_status != "PASS": FAIL; raise_warning: power_validation_status` + + +**Notes:** +1. on precision - my understanding is that the general rule for the RCT is that if a value is given in the standard and has four decimal places, the precision is to the nearest .0001. Minimum efficiency for chillers has values ranging between 0.5495 IPLV.IP and 0.7903 FL, which means that given the precision for chillers is about ~ 0.01% (1-). Suggest that for the capacity calculations, this precision is used, but for the power calculation, the square root of 0.01% (0.1%) is used, as this calculation is the result of two separate calculations multiplied together + + +**[Back](../_toc.md)** + + From aee3878c69e80966b8c8474898492dbe118128e5 Mon Sep 17 00:00:00 2001 From: KarenWGard <114143532+KarenWGard@users.noreply.github.com> Date: Mon, 16 Sep 2024 16:08:20 -0400 Subject: [PATCH 2/8] Update Rule22-42.md --- docs/section22/Rule22-42.md | 49 +++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/docs/section22/Rule22-42.md b/docs/section22/Rule22-42.md index bd6c485df0..9eab7eadb4 100644 --- a/docs/section22/Rule22-42.md +++ b/docs/section22/Rule22-42.md @@ -21,9 +21,9 @@ J-6 - get the chiller rated capacity: `rated_capacity = chiller.rated_capacity` - convert the chiller rated capacity from watts to tons: `chiller_capacity_tons = rated_capacity * 0.000284345` - check if the compressor type is CENTRIFUGAL: `if chiller.compressor_type == "CENTRIFUGAL":` - - if the capacity is less than 150 tons, the category is V: `if chiller_capacity_tons < 150: curve_set = "V"` - - else if the capacity is greater than or equal to 300 tons, the category is Y: `elif chiller_capacity_tons >= 300: curve_set = "Y"` - - otherwise, the capacity is between 150 and 300, so the curves set is X: `else: curve_set = "X"` + - if the capacity is less than 150 tons, the category is Z: `if chiller_capacity_tons < 150: curve_set = "Z"` + - else if the capacity is greater than or equal to 300 tons, the category is AB: `elif chiller_capacity_tons >= 300: curve_set = "AB"` + - otherwise, the capacity is between 150 and 300, so the curves set is AA: `else: curve_set = "AA"` - otherwise, check if the compressor type is POSITIVE_DISPLACEMENT or SCROLL: `if chiller.compressor_type in ["POSITIVE_DISPLACEMENT","SCROLL"]:` - if the capacity is less than 150 tons, the category is Z: `if chiller_capacity_tons < 150: curve_set = "Z"` - else if the capacity is greater than or equal to 300 tons, the category is AA: `elif chiller_capacity_tons >= 300: curve_set = "AA"` @@ -31,44 +31,45 @@ J-6 - continue if the curve set is not "NONE" - the curve set could be none if the chiller.compressor_type is not one of the recognized types for Appendix G: `if curve_set <> "NONE":` - calculate the chiller rated power by dividing the chiller rated capacity by the chiller full load efficiency (cop): `rated_power = chiller.rated_capacity / chiller.full_load_efficiency` - create a list of the expected capacity validation points - this is in 25% intervals, starting with 0.25 to 1: `expected_validation_plr = [0.25,0.5,0.75,1]` - - create a list of the expected temperatures for the chilled water temperature for the validation calculations - expected_chwt_temps - units are (F). The values are selected to capture the minimum, maximum, rating condition and some points in between: `expected_cwt_temps = [39,45,50,55]` - - create a list of the expected entering condenser temperatures for the condenser water temperature for the validation calculations - expected_ect_temps - units are (F). The values are selected to capture the minimum, maximum, rating condition and some points in between: `expected_ect_temps = [60,104,85,72.5,97.5]` + - create a list of the expected temperatures for the chilled water temperature for the validation calculations - expected_chwt_temps - units are (F). The values are selected to capture the minimum, maximum, rating condition and some points in between: `expected_chwt_temps = [39,45,50,55]` + - create a list of the expected entering condenser temperatures for the condenser water temperature for the validation calculations - expected_ecwt_temps - units are (F). The values are selected to capture the minimum, maximum, rating condition and some points in between: `expected_ecwt_temps = [60,104,85,72.5,97.5]` - get the coefficients for the EIR-f-T curve (IP units) using a table lookup for table J-6. This assumes that the lookup function will return a list with the coefficients in order (C1,C2,...): `eir_f_t_coefficients = table_J_2_lookup(curve_set,"EIR-f-T")` - get the coefficients for the CAP-f-T curve (IP units) using a table lookup for table J-6. This assumes that the lookup function will return a list with the coefficients in order (C1,C2,...): `cap_f_t_coefficients = table_J_2_lookup(curve_set,"Cap-f-T")` - get the coefficients for the PLR curve (IP units) using a table lookup for table J-6. This assumes that the lookup function will return a list with the coefficients in order (C1,C2,...): `plr_coefficients = table_J_2_lookup(curve_set,"EIR-f-PLR")` - - create a variable (capacity_validation_status) to track whether the capacity validation passes and set it to "PASS" - if the capacity validation fails at any point, this variable will change to give the values at which the capacity validation failed: `capacity_validation_status = "PASS"` - - create a variable (power_validation_status) to track whether the power validation passes and set it to "PASS" - if the power validation fails at any point, this variable will change to give the values at which teh power validation failed: `power_validation_status = "PASS" - - convert the chiller.capacity_validation_points to a dictionary with the keys being a list of two values - [chilled_water_supply_temperature, condenser_temperature], and values being the capacity_validation_point itself. Sorting the validation points will allow the calculations that follow to be much simpler. Start by creating a dict capacity_validation_pts_dict: `capacity_validation_pts_dict = {}` - look at each value in chiller.capacity_validation_points: `for capacity_validation_point in chiller.capacity_validation_points:` - - add the point to capacity_validation_pts_dict: `capacity_validation_pts_dict[[capacity_validation_point.chilled_water_supply_temperature, capacity_validation_point.condenser_temperature]] = capacity_validation_point` + - add the point to capacity_validation_pts_dict: `capacity_validation_pts_dict[[capacity_validation_point.chilled_water_supply_temperature, capacity_validation_point.condenser_temperature]] = capacity_validation_point.result` - do the same conversion with the chiller.power_validation_points and storing the results in power_validation_pts_dict. However in this case, the values are a list of points because we expect different loads at each point: `power_validation_pts_dict = {}` - look at each value in chiller.power_validation_points: `for power_validation_point in chiller.power_validation_points:` - set the default to a blank list: `power_validation_pts_dict.setdefault([[power_validation_point.chilled_water_supply_temperature, power_validation_point.condenser_temperature]], [])` - - append the power validation point to the list at this given: `power_validation_pts_dict[[power_validation_point.chilled_water_supply_temperature, power_validation_point.condenser_temperature]].append(power_validation_point)` + - append the power validation point to the list at this given: `power_validation_pts_dict[[power_validation_point.chilled_water_supply_temperature, power_validation_point.condenser_temperature]].append(power_validation_point.result)` - create a dictionary of the expected capacities for use in the power validation check: `given_capacities = {}` - the following lines or logic do the capacity validation check: - - loop through the expected_cwt_temps: `for cwt in expected_cwt_temps:` - - loop through each expected_ect_temps: `for ect in expected_ect_temps:` + - create a list of non-matching capacity validation points: `non_matching_capacity_validation_points = []` + - create a list of missing capacity validation points: `missing_capacity_validation_points = []` + - loop through the expected_chwt_temps: `for cwt in expected_cwt_temps:` + - loop through each expected_ecwt_temps: `for ect in expected_ecwt_temps:` - look for the capacity validation point in capacity_validation_pts_dict: `if capacity_validation_pts_dict[[cwt, ect]]:` - calculate the expected capacity by multiplying the result of the formula by the rated_capacity: `expected_capacity = (cap_f_t_coefficients[0] + cap_f_t_coefficients[1] * cwt + cap_f_t_coefficients[2] * cwt^2 + cap_f_t_coefficients[3] * ect + cap_f_t_coefficients[4] * ect^2 + cap_f_t_coefficients[5] * cwt * ect) * rated_capacity` - - get the given capacity: `given_capacity = capacity_validation_pts_dict[[cwt, ect]].result` - - if the expected capacity matches the given capacity, add the expected capacity to the expected_capacities dictionary. This should not be an exact match, but with a margin of error (see notes at the bottom for suggested margins of errors): `if expected_capacity == given_capacity: given_capacities[[cwt,ect]] = given_capacity` - - otherwise, if the expected capacity doesn't match the given capacity, then change capacity_validation_status and go to Rule Assertion: `else: capacity_validation_status = "Expected capacity does not match given capacity at CHWT: " + cwt + " & ECT: " + ect; GO TO RULE ASSERTION` - - otherwise this value doesn't exist, set the capacity_validation_status and go to rule assertion: `else: capacity_validation_status = "Required capacity validation point is missing. Expected CHWT: " + cwt + ", expected ECT: " + ect; GO TO RULE ASSERTION` + - get the given capacity: `given_capacity = capacity_validation_pts_dict[[cwt, ect]]` + - add the given capacity to the given_capacities dictionary: `given_capacities[[cwt,ect]] = given_capacity` + - Compare the expected capacity to the given capacity. This should not be an exact match, but with a margin of error (see notes at the bottom for suggested margins of errors). We don't need to do anything if the capacities match, but if they don't match we need to add the conditions to the non_matching_capacity_validation_points list: `if expected_capacity != given_capacity: non_matching_capacity_validation_points.append({"CHWT": cwt, "ECWT": ect})` + - otherwise this value doesn't exist, append these conditions to the missing_capacity_validation_points list: `else: missing_capacity_validation_points.append({"CHWT": cwt, "ECWT": ect})` - the following lines or logic do the power validation check: + - create a list of non-matching power validation points: `non_matching_power_validation_points = []` + - create a list of missing power validation points: `missing_power_validation_points = []` - loop through the expected_cwt_temps: `for cwt in expected_cwt_temps:` - - loop through each expected_ect_temps: `for ect in expected_ect_temps:` + - loop through each expected_ecwt_temps: `for ect in expected_ecwt_temps:` - look for the power validation points in power_validation_pts_dict: `if power_validation_pts_dict[[cwt, ect]]:` - we are expecting to see multiple validation points aligning with the expected_validation_plr. Create a list of part load ratios that are given. Later we'll compare this with the expected list to make sure that all points are given: `given_plrs = []` - - look at each power validation point in the list: `for power_validation_point in power_validation_pts_dict[[cwt, ect]]:` + - look at each power validation point in the list: `for power_validation_point_result in power_validation_pts_dict[[cwt, ect]]:` - get the load: `load = power_validation_point.load` - - get the given power: `given_power = power_validation_point.result` + - get the given power: `given_power = power_validation_point_result` - calculate the PLR by dividing the load by the given capacity at these operating conditions: `plr = load / given_capacities[[cwt, ect]]` - check whether the plr is one of the plrs that we need to check: `if plr in expected_validation_plr:` - add the plr to the list of plrs provided: `given_plrs.append(plr)` @@ -80,13 +81,13 @@ J-6 - Chiller operating power = given_capacity[[cwt, ect]] × EIR-f-T × EIR-f-PLR × Chiller Input Power at Rated Conditions/Chiller Capacity at Rated Conditions - `expected_power = given_capacity[[cwt, ect]] * eir_ft * eir_plr * rated_power/rated_capacity` - - check whether the expected power and the given power are equal. This should not be an exact match, but with a margin of error (see notes at the bottom for suggested margins of errors). If the expected power and given power do not match, update power_validation_status and GO TO RULE ASSERTION: `if expected_power != given_power: power_validation_status = "Expected power does not match given power at CHWT: " + cwt + ", ECT: " + ect + " & " + plr".; GO TO RULE ASSERTION` - - make sure that all of the expected plrs are covered by + - check whether the expected power and the given power are equal. This should not be an exact match, but with a margin of error (see notes at the bottom for suggested margins of errors). If the expected power and given power do not match, add the conditions to the non_matching_power_validation_points list: `if expected_power != given_power: non_matching_power_validation_points.append({"CHWT": cwt, "ECWT": ect, "PLR": plr})` + - otherwise, this particular plr is not given, append these conditions to the missing_power_validation_points list: `missing_power_validation_points.append({"CHWT": cwt, "ECWT": ect, "PLR": plr})` + - otherwise, this point isn't given, append these conditions to the missing_power_validation_points list: `missing_power_validation_points.append({"CHWT": cwt, "ECWT": ect, "PLR": "ALL"})` **Rule Assertion:** - - Case 1: both power_validation_status and capacity_validation_status are PASS: PASS: `if power_validation_status == capacity_validation_status == "PASS"; PASS` - - Case 2: capacity validation status is not PASS, return fail and raise warning with the capacity_validation_status as an additional message: `if capacity_validation_status != "PASS": FAIL; raise_warning: capacity_validation_status` - - Case 3: power validation status is not PASS, return fail and raise warning with the power_validation_status as an additional message: `if power_validation_status != "PASS": FAIL; raise_warning: power_validation_status` + - Case 1: all lists of missing or non-matching validation points have a length of zero: PASS: `if len(non_matching_capacity_validation_points) == len(missing_capacity_validation_points) == len(non_matching_power_validation_points) == len(missing_power_validation_points) == 0: PASS` + - Case 2: all other cases fail: `else: FAIL` **Notes:** From 1de24bfd52ee6854d12681e051734bb4adfdb3d2 Mon Sep 17 00:00:00 2001 From: KarenWGard <114143532+KarenWGard@users.noreply.github.com> Date: Tue, 19 Nov 2024 14:04:51 -0500 Subject: [PATCH 3/8] Update Rule22-42.md --- docs/section22/Rule22-42.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/section22/Rule22-42.md b/docs/section22/Rule22-42.md index 9eab7eadb4..840a2a7ff9 100644 --- a/docs/section22/Rule22-42.md +++ b/docs/section22/Rule22-42.md @@ -25,9 +25,9 @@ J-6 - else if the capacity is greater than or equal to 300 tons, the category is AB: `elif chiller_capacity_tons >= 300: curve_set = "AB"` - otherwise, the capacity is between 150 and 300, so the curves set is AA: `else: curve_set = "AA"` - otherwise, check if the compressor type is POSITIVE_DISPLACEMENT or SCROLL: `if chiller.compressor_type in ["POSITIVE_DISPLACEMENT","SCROLL"]:` - - if the capacity is less than 150 tons, the category is Z: `if chiller_capacity_tons < 150: curve_set = "Z"` - - else if the capacity is greater than or equal to 300 tons, the category is AA: `elif chiller_capacity_tons >= 300: curve_set = "AA"` - - otherwise, the capacity is between 150 and 300, so the curves set is AB: `else: curve_set = "AB"` + - if the capacity is less than 150 tons, the category is V: `if chiller_capacity_tons < 150: curve_set = "V"` + - else if the capacity is greater than or equal to 300 tons, the category is AA: `elif chiller_capacity_tons >= 300: curve_set = "Y"` + - otherwise, the capacity is between 150 and 300, so the curves set is AB: `else: curve_set = "X"` - continue if the curve set is not "NONE" - the curve set could be none if the chiller.compressor_type is not one of the recognized types for Appendix G: `if curve_set <> "NONE":` - calculate the chiller rated power by dividing the chiller rated capacity by the chiller full load efficiency (cop): `rated_power = chiller.rated_capacity / chiller.full_load_efficiency` - create a list of the expected capacity validation points - this is in 25% intervals, starting with 0.25 to 1: `expected_validation_plr = [0.25,0.5,0.75,1]` From c709250bbc6630c6f098f78f05af62e02a2d1281 Mon Sep 17 00:00:00 2001 From: KarenWGard <114143532+KarenWGard@users.noreply.github.com> Date: Wed, 4 Dec 2024 16:22:53 -0500 Subject: [PATCH 4/8] Update Rule22-42.md --- docs/section22/Rule22-42.md | 44 +++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/docs/section22/Rule22-42.md b/docs/section22/Rule22-42.md index 840a2a7ff9..81b171ac4d 100644 --- a/docs/section22/Rule22-42.md +++ b/docs/section22/Rule22-42.md @@ -9,7 +9,7 @@ **Mandatory Rule:** True **Evaluation Context:** Each Chiller **Table Lookup:** -J-6 +J-6 **Function Call:** ## Applicability Check: @@ -22,25 +22,26 @@ J-6 - convert the chiller rated capacity from watts to tons: `chiller_capacity_tons = rated_capacity * 0.000284345` - check if the compressor type is CENTRIFUGAL: `if chiller.compressor_type == "CENTRIFUGAL":` - if the capacity is less than 150 tons, the category is Z: `if chiller_capacity_tons < 150: curve_set = "Z"` - - else if the capacity is greater than or equal to 300 tons, the category is AB: `elif chiller_capacity_tons >= 300: curve_set = "AB"` - - otherwise, the capacity is between 150 and 300, so the curves set is AA: `else: curve_set = "AA"` - - otherwise, check if the compressor type is POSITIVE_DISPLACEMENT or SCROLL: `if chiller.compressor_type in ["POSITIVE_DISPLACEMENT","SCROLL"]:` + - otherwise, if the capacity is between 150 and 300 tons, the category is AA: `elif (chiller_capacity_tons >= 150) and (chiller_capacity_tons < 300): curve_set = "AA"` + - else the capacity is greater than or equal to 300 tons, the category is AB: `else: curve_set = "AB"` + - otherwise, check if the compressor type is POSITIVE_DISPLACEMENT or SCROLL: `if chiller.compressor_type in ["POSITIVE_DISPLACEMENT","SCROLL","SCREW"]:` - if the capacity is less than 150 tons, the category is V: `if chiller_capacity_tons < 150: curve_set = "V"` - else if the capacity is greater than or equal to 300 tons, the category is AA: `elif chiller_capacity_tons >= 300: curve_set = "Y"` - otherwise, the capacity is between 150 and 300, so the curves set is AB: `else: curve_set = "X"` - continue if the curve set is not "NONE" - the curve set could be none if the chiller.compressor_type is not one of the recognized types for Appendix G: `if curve_set <> "NONE":` - calculate the chiller rated power by dividing the chiller rated capacity by the chiller full load efficiency (cop): `rated_power = chiller.rated_capacity / chiller.full_load_efficiency` - create a list of the expected capacity validation points - this is in 25% intervals, starting with 0.25 to 1: `expected_validation_plr = [0.25,0.5,0.75,1]` - - create a list of the expected temperatures for the chilled water temperature for the validation calculations - expected_chwt_temps - units are (F). The values are selected to capture the minimum, maximum, rating condition and some points in between: `expected_chwt_temps = [39,45,50,55]` - - create a list of the expected entering condenser temperatures for the condenser water temperature for the validation calculations - expected_ecwt_temps - units are (F). The values are selected to capture the minimum, maximum, rating condition and some points in between: `expected_ecwt_temps = [60,104,85,72.5,97.5]` + - create a list of the expected temperatures for the chilled water temperature for the validation calculations - expected_cwt_temps - units are (F). The values are selected to capture the minimum, maximum, rating condition and some points in between: `expected_cwt_temps = [39,45,50,55]` + - create a list of the expected entering condenser temperatures for the condenser water temperature for the validation calculations - expected_ect_temps - units are (F). The values are selected to capture the minimum, maximum, rating condition and some points in between: `expected_ect_temps = [60,104,85,72.5,97.5]` - - get the coefficients for the EIR-f-T curve (IP units) using a table lookup for table J-6. This assumes that the lookup function will return a list with the coefficients in order (C1,C2,...): `eir_f_t_coefficients = table_J_2_lookup(curve_set,"EIR-f-T")` - - get the coefficients for the CAP-f-T curve (IP units) using a table lookup for table J-6. This assumes that the lookup function will return a list with the coefficients in order (C1,C2,...): `cap_f_t_coefficients = table_J_2_lookup(curve_set,"Cap-f-T")` - - get the coefficients for the PLR curve (IP units) using a table lookup for table J-6. This assumes that the lookup function will return a list with the coefficients in order (C1,C2,...): `plr_coefficients = table_J_2_lookup(curve_set,"EIR-f-PLR")` + - get the coefficients for the EIR-f-T curve (IP units) using a table lookup for table J-6. This assumes that the lookup function will return a list with the coefficients in order (C1,C2,...): `eir_f_t_coefficients = table_J_6_lookup(curve_set,"EIR-f-T")` + - get the coefficients for the CAP-f-T curve (IP units) using a table lookup for table J-6. This assumes that the lookup function will return a list with the coefficients in order (C1,C2,...): `cap_f_t_coefficients = table_J_6_lookup(curve_set,"Cap-f-T")` + - get the coefficients for the PLR curve (IP units) using a table lookup for table J-6. This assumes that the lookup function will return a list with the coefficients in order (C1,C2,...): `plr_coefficients = table_J_6_lookup(curve_set,"EIR-f-PLR")` - convert the chiller.capacity_validation_points to a dictionary with the keys being a list of two values - [chilled_water_supply_temperature, condenser_temperature], and values being the capacity_validation_point itself. Sorting the validation points will allow the calculations that follow to be much simpler. Start by creating a dict capacity_validation_pts_dict: `capacity_validation_pts_dict = {}` - look at each value in chiller.capacity_validation_points: `for capacity_validation_point in chiller.capacity_validation_points:` - - add the point to capacity_validation_pts_dict: `capacity_validation_pts_dict[[capacity_validation_point.chilled_water_supply_temperature, capacity_validation_point.condenser_temperature]] = capacity_validation_point.result` + - create the key: `dict_key = f"{capacity_validation_point.chilled_water_supply_temperature}, {capacity_validation_point.condenser_temperature}"` + - add the point to capacity_validation_pts_dict: `capacity_validation_pts_dict[dict_key] = capacity_validation_point.result` - do the same conversion with the chiller.power_validation_points and storing the results in power_validation_pts_dict. However in this case, the values are a list of points because we expect different loads at each point: `power_validation_pts_dict = {}` - look at each value in chiller.power_validation_points: `for power_validation_point in chiller.power_validation_points:` @@ -51,20 +52,21 @@ J-6 - the following lines or logic do the capacity validation check: - create a list of non-matching capacity validation points: `non_matching_capacity_validation_points = []` - create a list of missing capacity validation points: `missing_capacity_validation_points = []` - - loop through the expected_chwt_temps: `for cwt in expected_cwt_temps:` - - loop through each expected_ecwt_temps: `for ect in expected_ecwt_temps:` - - look for the capacity validation point in capacity_validation_pts_dict: `if capacity_validation_pts_dict[[cwt, ect]]:` + - loop through the expected_cwt_temps: `for cwt in expected_cwt_temps:` + - loop through each expected_ect_temps: `for ect in expected_ect_temps:` + - create the key: `dict_key = f"{cwt}, {ect}"` + - look for the capacity validation point in capacity_validation_pts_dict: `if capacity_validation_pts_dict[dict_key]:` - calculate the expected capacity by multiplying the result of the formula by the rated_capacity: `expected_capacity = (cap_f_t_coefficients[0] + cap_f_t_coefficients[1] * cwt + cap_f_t_coefficients[2] * cwt^2 + cap_f_t_coefficients[3] * ect + cap_f_t_coefficients[4] * ect^2 + cap_f_t_coefficients[5] * cwt * ect) * rated_capacity` - - get the given capacity: `given_capacity = capacity_validation_pts_dict[[cwt, ect]]` + - get the given capacity: `given_capacity = capacity_validation_pts_dict[dict_key]` - add the given capacity to the given_capacities dictionary: `given_capacities[[cwt,ect]] = given_capacity` - - Compare the expected capacity to the given capacity. This should not be an exact match, but with a margin of error (see notes at the bottom for suggested margins of errors). We don't need to do anything if the capacities match, but if they don't match we need to add the conditions to the non_matching_capacity_validation_points list: `if expected_capacity != given_capacity: non_matching_capacity_validation_points.append({"CHWT": cwt, "ECWT": ect})` - - otherwise this value doesn't exist, append these conditions to the missing_capacity_validation_points list: `else: missing_capacity_validation_points.append({"CHWT": cwt, "ECWT": ect})` + - Compare the expected capacity to the given capacity. This should not be an exact match, but with a margin of error (see notes at the bottom for suggested margins of errors). We don't need to do anything if the capacities match, but if they don't match we need to add the conditions to the non_matching_capacity_validation_points list: `if expected_capacity != given_capacity: non_matching_capacity_validation_points.append({"CWT": cwt, "ECT": ect})` + - otherwise this value doesn't exist, append these conditions to the missing_capacity_validation_points list: `else: missing_capacity_validation_points.append({"CWT": cwt, "ECT": ect})` - the following lines or logic do the power validation check: - create a list of non-matching power validation points: `non_matching_power_validation_points = []` - create a list of missing power validation points: `missing_power_validation_points = []` - loop through the expected_cwt_temps: `for cwt in expected_cwt_temps:` - - loop through each expected_ecwt_temps: `for ect in expected_ecwt_temps:` + - loop through each expected_ect_temps: `for ect in expected_ect_temps:` - look for the power validation points in power_validation_pts_dict: `if power_validation_pts_dict[[cwt, ect]]:` - we are expecting to see multiple validation points aligning with the expected_validation_plr. Create a list of part load ratios that are given. Later we'll compare this with the expected list to make sure that all points are given: `given_plrs = []` - look at each power validation point in the list: `for power_validation_point_result in power_validation_pts_dict[[cwt, ect]]:` @@ -74,16 +76,16 @@ J-6 - check whether the plr is one of the plrs that we need to check: `if plr in expected_validation_plr:` - add the plr to the list of plrs provided: `given_plrs.append(plr)` - calculate eir_plr using the coefficients given: `eir_plr = plr_coefficients[0] + plr_coefficients[1] * plr + plr_coefficients[2] * plr^2` - - calculate the eir_ft using the coefficients given: `eir_ft = eir_f_t_coefficients[0] + eir_f_t_coefficients[1] * cwt + eir_f_t_coefficients[2] * cwt^2 + eir_f_t_coefficients[3] * ect + eir_f_t_coefficients[4] * ect^2 + eir_f_t_coefficients[5] * cwt * ect + - calculate the eir_ft using the coefficients given: `eir_ft = eir_f_t_coefficients[0] + eir_f_t_coefficients[1] * cwt + eir_f_t_coefficients[2] * cwt^2 + eir_f_t_coefficients[3] * ect + eir_f_t_coefficients[4] * ect^2 + eir_f_t_coefficients[5] * cwt * ect` - calculate the expected power using the formula: - Chiller operating power = Rated Capacity × CAP-f-T × EIR-f-T × EIR-f-PLR × Chiller Input Power at Rated Conditions/Chiller Capacity at Rated Conditions - in this case, the given capacity under these operating conditions is the rated capacity * cap_ft, so the modified formula is: - Chiller operating power = given_capacity[[cwt, ect]] × EIR-f-T × EIR-f-PLR × Chiller Input Power at Rated Conditions/Chiller Capacity at Rated Conditions - `expected_power = given_capacity[[cwt, ect]] * eir_ft * eir_plr * rated_power/rated_capacity` - - check whether the expected power and the given power are equal. This should not be an exact match, but with a margin of error (see notes at the bottom for suggested margins of errors). If the expected power and given power do not match, add the conditions to the non_matching_power_validation_points list: `if expected_power != given_power: non_matching_power_validation_points.append({"CHWT": cwt, "ECWT": ect, "PLR": plr})` - - otherwise, this particular plr is not given, append these conditions to the missing_power_validation_points list: `missing_power_validation_points.append({"CHWT": cwt, "ECWT": ect, "PLR": plr})` - - otherwise, this point isn't given, append these conditions to the missing_power_validation_points list: `missing_power_validation_points.append({"CHWT": cwt, "ECWT": ect, "PLR": "ALL"})` + - check whether the expected power and the given power are equal. This should not be an exact match, but with a margin of error (see notes at the bottom for suggested margins of errors). If the expected power and given power do not match, add the conditions to the non_matching_power_validation_points list: `if expected_power != given_power: non_matching_power_validation_points.append({"CWT": cwt, "ECT": ect, "PLR": plr})` + - otherwise, this particular plr is not given, append these conditions to the missing_power_validation_points list: `missing_power_validation_points.append({"CWT": cwt, "ECT": ect, "PLR": plr})` + - otherwise, this point isn't given, append these conditions to the missing_power_validation_points list: `missing_power_validation_points.append({"CWT": cwt, "ECT": ect, "PLR": "ALL"})` **Rule Assertion:** - Case 1: all lists of missing or non-matching validation points have a length of zero: PASS: `if len(non_matching_capacity_validation_points) == len(missing_capacity_validation_points) == len(non_matching_power_validation_points) == len(missing_power_validation_points) == 0: PASS` From 20ddb2da2205a7375266508483d899bd4fa663d1 Mon Sep 17 00:00:00 2001 From: KarenWGard <114143532+KarenWGard@users.noreply.github.com> Date: Wed, 4 Dec 2024 16:27:38 -0500 Subject: [PATCH 5/8] Update Rule22-42.md --- docs/section22/Rule22-42.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/section22/Rule22-42.md b/docs/section22/Rule22-42.md index 81b171ac4d..1735969801 100644 --- a/docs/section22/Rule22-42.md +++ b/docs/section22/Rule22-42.md @@ -73,15 +73,13 @@ J-6 - get the load: `load = power_validation_point.load` - get the given power: `given_power = power_validation_point_result` - calculate the PLR by dividing the load by the given capacity at these operating conditions: `plr = load / given_capacities[[cwt, ect]]` - - check whether the plr is one of the plrs that we need to check: `if plr in expected_validation_plr:` + - check whether the plr is one of the plrs that we need to check - note to dev team, please accept a match that is with 0.01 of the expected: `if plr in expected_validation_plr:` - add the plr to the list of plrs provided: `given_plrs.append(plr)` - calculate eir_plr using the coefficients given: `eir_plr = plr_coefficients[0] + plr_coefficients[1] * plr + plr_coefficients[2] * plr^2` - calculate the eir_ft using the coefficients given: `eir_ft = eir_f_t_coefficients[0] + eir_f_t_coefficients[1] * cwt + eir_f_t_coefficients[2] * cwt^2 + eir_f_t_coefficients[3] * ect + eir_f_t_coefficients[4] * ect^2 + eir_f_t_coefficients[5] * cwt * ect` - calculate the expected power using the formula: - Chiller operating power = Rated Capacity × CAP-f-T × EIR-f-T × EIR-f-PLR × Chiller Input Power at Rated Conditions/Chiller Capacity at Rated Conditions - - in this case, the given capacity under these operating conditions is the rated capacity * cap_ft, so the modified formula is: - - Chiller operating power = given_capacity[[cwt, ect]] × EIR-f-T × EIR-f-PLR × Chiller Input Power at Rated Conditions/Chiller Capacity at Rated Conditions - + - in this case, the given capacity under these operating conditions is the rated capacity * cap_ft, so the modified formula is as follows: - `expected_power = given_capacity[[cwt, ect]] * eir_ft * eir_plr * rated_power/rated_capacity` - check whether the expected power and the given power are equal. This should not be an exact match, but with a margin of error (see notes at the bottom for suggested margins of errors). If the expected power and given power do not match, add the conditions to the non_matching_power_validation_points list: `if expected_power != given_power: non_matching_power_validation_points.append({"CWT": cwt, "ECT": ect, "PLR": plr})` - otherwise, this particular plr is not given, append these conditions to the missing_power_validation_points list: `missing_power_validation_points.append({"CWT": cwt, "ECT": ect, "PLR": plr})` From 5dd22dc8a40f625abdf0b2d0bb9bde62eb0f585a Mon Sep 17 00:00:00 2001 From: KarenWGard <114143532+KarenWGard@users.noreply.github.com> Date: Wed, 11 Dec 2024 09:07:12 -0500 Subject: [PATCH 6/8] Update Rule22-42.md --- docs/section22/Rule22-42.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/section22/Rule22-42.md b/docs/section22/Rule22-42.md index 1735969801..792775505e 100644 --- a/docs/section22/Rule22-42.md +++ b/docs/section22/Rule22-42.md @@ -32,7 +32,7 @@ J-6 - calculate the chiller rated power by dividing the chiller rated capacity by the chiller full load efficiency (cop): `rated_power = chiller.rated_capacity / chiller.full_load_efficiency` - create a list of the expected capacity validation points - this is in 25% intervals, starting with 0.25 to 1: `expected_validation_plr = [0.25,0.5,0.75,1]` - create a list of the expected temperatures for the chilled water temperature for the validation calculations - expected_cwt_temps - units are (F). The values are selected to capture the minimum, maximum, rating condition and some points in between: `expected_cwt_temps = [39,45,50,55]` - - create a list of the expected entering condenser temperatures for the condenser water temperature for the validation calculations - expected_ect_temps - units are (F). The values are selected to capture the minimum, maximum, rating condition and some points in between: `expected_ect_temps = [60,104,85,72.5,97.5]` + - create a list of the expected entering condenser temperatures for the condenser water temperature for the validation calculations - expected_ecwt_temps - units are (F). The values are selected to capture the minimum, maximum, rating condition and some points in between: `expected_ecwt_temps = [60,104,85,72.5,97.5]` - get the coefficients for the EIR-f-T curve (IP units) using a table lookup for table J-6. This assumes that the lookup function will return a list with the coefficients in order (C1,C2,...): `eir_f_t_coefficients = table_J_6_lookup(curve_set,"EIR-f-T")` - get the coefficients for the CAP-f-T curve (IP units) using a table lookup for table J-6. This assumes that the lookup function will return a list with the coefficients in order (C1,C2,...): `cap_f_t_coefficients = table_J_6_lookup(curve_set,"Cap-f-T")` @@ -53,37 +53,37 @@ J-6 - create a list of non-matching capacity validation points: `non_matching_capacity_validation_points = []` - create a list of missing capacity validation points: `missing_capacity_validation_points = []` - loop through the expected_cwt_temps: `for cwt in expected_cwt_temps:` - - loop through each expected_ect_temps: `for ect in expected_ect_temps:` - - create the key: `dict_key = f"{cwt}, {ect}"` + - loop through each expected_ecwt_temps: `for ecwt in expected_ecwt_temps:` + - create the key: `dict_key = f"{cwt}, {ecwt}"` - look for the capacity validation point in capacity_validation_pts_dict: `if capacity_validation_pts_dict[dict_key]:` - - calculate the expected capacity by multiplying the result of the formula by the rated_capacity: `expected_capacity = (cap_f_t_coefficients[0] + cap_f_t_coefficients[1] * cwt + cap_f_t_coefficients[2] * cwt^2 + cap_f_t_coefficients[3] * ect + cap_f_t_coefficients[4] * ect^2 + cap_f_t_coefficients[5] * cwt * ect) * rated_capacity` + - calculate the expected capacity by multiplying the result of the formula by the rated_capacity: `expected_capacity = (cap_f_t_coefficients[0] + cap_f_t_coefficients[1] * cwt + cap_f_t_coefficients[2] * cwt^2 + cap_f_t_coefficients[3] * ecwt + cap_f_t_coefficients[4] * ecwt^2 + cap_f_t_coefficients[5] * cwt * ecwt) * rated_capacity` - get the given capacity: `given_capacity = capacity_validation_pts_dict[dict_key]` - - add the given capacity to the given_capacities dictionary: `given_capacities[[cwt,ect]] = given_capacity` - - Compare the expected capacity to the given capacity. This should not be an exact match, but with a margin of error (see notes at the bottom for suggested margins of errors). We don't need to do anything if the capacities match, but if they don't match we need to add the conditions to the non_matching_capacity_validation_points list: `if expected_capacity != given_capacity: non_matching_capacity_validation_points.append({"CWT": cwt, "ECT": ect})` - - otherwise this value doesn't exist, append these conditions to the missing_capacity_validation_points list: `else: missing_capacity_validation_points.append({"CWT": cwt, "ECT": ect})` + - add the given capacity to the given_capacities dictionary: `given_capacities[[cwt,ecwt]] = given_capacity` + - Compare the expected capacity to the given capacity. This should not be an exact match, but with a margin of error (see notes at the bottom for suggested margins of errors). We don't need to do anything if the capacities match, but if they don't match we need to add the conditions to the non_matching_capacity_validation_points list: `if expected_capacity != given_capacity: non_matching_capacity_validation_points.append({"CWT": cwt, "ECWT": ecwt})` + - otherwise this value doesn't exist, append these conditions to the missing_capacity_validation_points list: `else: missing_capacity_validation_points.append({"CWT": cwt, "ECWT": ecwt})` - the following lines or logic do the power validation check: - create a list of non-matching power validation points: `non_matching_power_validation_points = []` - create a list of missing power validation points: `missing_power_validation_points = []` - loop through the expected_cwt_temps: `for cwt in expected_cwt_temps:` - - loop through each expected_ect_temps: `for ect in expected_ect_temps:` - - look for the power validation points in power_validation_pts_dict: `if power_validation_pts_dict[[cwt, ect]]:` + - loop through each expected_ect_temps: `for ecwt in expected_ecwt_temps:` + - look for the power validation points in power_validation_pts_dict: `if power_validation_pts_dict[[cwt, ecwt]]:` - we are expecting to see multiple validation points aligning with the expected_validation_plr. Create a list of part load ratios that are given. Later we'll compare this with the expected list to make sure that all points are given: `given_plrs = []` - - look at each power validation point in the list: `for power_validation_point_result in power_validation_pts_dict[[cwt, ect]]:` + - look at each power validation point in the list: `for power_validation_point_result in power_validation_pts_dict[[cwt, ecwt]]:` - get the load: `load = power_validation_point.load` - get the given power: `given_power = power_validation_point_result` - - calculate the PLR by dividing the load by the given capacity at these operating conditions: `plr = load / given_capacities[[cwt, ect]]` + - calculate the PLR by dividing the load by the given capacity at these operating conditions: `plr = load / given_capacities[[cwt, ecwt]]` - check whether the plr is one of the plrs that we need to check - note to dev team, please accept a match that is with 0.01 of the expected: `if plr in expected_validation_plr:` - add the plr to the list of plrs provided: `given_plrs.append(plr)` - calculate eir_plr using the coefficients given: `eir_plr = plr_coefficients[0] + plr_coefficients[1] * plr + plr_coefficients[2] * plr^2` - - calculate the eir_ft using the coefficients given: `eir_ft = eir_f_t_coefficients[0] + eir_f_t_coefficients[1] * cwt + eir_f_t_coefficients[2] * cwt^2 + eir_f_t_coefficients[3] * ect + eir_f_t_coefficients[4] * ect^2 + eir_f_t_coefficients[5] * cwt * ect` + - calculate the eir_ft using the coefficients given: `eir_ft = eir_f_t_coefficients[0] + eir_f_t_coefficients[1] * cwt + eir_f_t_coefficients[2] * cwt^2 + eir_f_t_coefficients[3] * ecwt + eir_f_t_coefficients[4] * ecwt^2 + eir_f_t_coefficients[5] * cwt * ecwt` - calculate the expected power using the formula: - Chiller operating power = Rated Capacity × CAP-f-T × EIR-f-T × EIR-f-PLR × Chiller Input Power at Rated Conditions/Chiller Capacity at Rated Conditions - in this case, the given capacity under these operating conditions is the rated capacity * cap_ft, so the modified formula is as follows: - - `expected_power = given_capacity[[cwt, ect]] * eir_ft * eir_plr * rated_power/rated_capacity` - - check whether the expected power and the given power are equal. This should not be an exact match, but with a margin of error (see notes at the bottom for suggested margins of errors). If the expected power and given power do not match, add the conditions to the non_matching_power_validation_points list: `if expected_power != given_power: non_matching_power_validation_points.append({"CWT": cwt, "ECT": ect, "PLR": plr})` - - otherwise, this particular plr is not given, append these conditions to the missing_power_validation_points list: `missing_power_validation_points.append({"CWT": cwt, "ECT": ect, "PLR": plr})` - - otherwise, this point isn't given, append these conditions to the missing_power_validation_points list: `missing_power_validation_points.append({"CWT": cwt, "ECT": ect, "PLR": "ALL"})` + - `expected_power = given_capacity[[cwt, ecwt]] * eir_ft * eir_plr * rated_power/rated_capacity` + - check whether the expected power and the given power are equal. This should not be an exact match, but with a margin of error (see notes at the bottom for suggested margins of errors). If the expected power and given power do not match, add the conditions to the non_matching_power_validation_points list: `if expected_power != given_power: non_matching_power_validation_points.append({"CWT": cwt, "ECWT": ecwt, "PLR": plr})` + - otherwise, this particular plr is not given, append these conditions to the missing_power_validation_points list: `missing_power_validation_points.append({"CWT": cwt, "ECWT": ecwt, "PLR": plr})` + - otherwise, this point isn't given, append these conditions to the missing_power_validation_points list: `missing_power_validation_points.append({"CWT": cwt, "ECWT": ecwt, "PLR": "ALL"})` **Rule Assertion:** - Case 1: all lists of missing or non-matching validation points have a length of zero: PASS: `if len(non_matching_capacity_validation_points) == len(missing_capacity_validation_points) == len(non_matching_power_validation_points) == len(missing_power_validation_points) == 0: PASS` From 4cfa6b94289e3ea4dd61bcb63161b3d342bbeef3 Mon Sep 17 00:00:00 2001 From: KarenWGard <114143532+KarenWGard@users.noreply.github.com> Date: Wed, 11 Dec 2024 09:14:33 -0500 Subject: [PATCH 7/8] Update Rule22-42.md --- docs/section22/Rule22-42.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/section22/Rule22-42.md b/docs/section22/Rule22-42.md index 792775505e..ee74843e21 100644 --- a/docs/section22/Rule22-42.md +++ b/docs/section22/Rule22-42.md @@ -45,8 +45,9 @@ J-6 - do the same conversion with the chiller.power_validation_points and storing the results in power_validation_pts_dict. However in this case, the values are a list of points because we expect different loads at each point: `power_validation_pts_dict = {}` - look at each value in chiller.power_validation_points: `for power_validation_point in chiller.power_validation_points:` - - set the default to a blank list: `power_validation_pts_dict.setdefault([[power_validation_point.chilled_water_supply_temperature, power_validation_point.condenser_temperature]], [])` - - append the power validation point to the list at this given: `power_validation_pts_dict[[power_validation_point.chilled_water_supply_temperature, power_validation_point.condenser_temperature]].append(power_validation_point.result)` + - create the key: `dict_key = f"{power_validation_point.chilled_water_supply_temperature}, {power_validation_point.condenser_temperature}"` + - set the default to a blank list: `power_validation_pts_dict.setdefault([dict_key], [])` + - append the power validation point to the list at this given: `power_validation_pts_dict[dict_key].append(power_validation_point.result)` - create a dictionary of the expected capacities for use in the power validation check: `given_capacities = {}` - the following lines or logic do the capacity validation check: @@ -58,7 +59,7 @@ J-6 - look for the capacity validation point in capacity_validation_pts_dict: `if capacity_validation_pts_dict[dict_key]:` - calculate the expected capacity by multiplying the result of the formula by the rated_capacity: `expected_capacity = (cap_f_t_coefficients[0] + cap_f_t_coefficients[1] * cwt + cap_f_t_coefficients[2] * cwt^2 + cap_f_t_coefficients[3] * ecwt + cap_f_t_coefficients[4] * ecwt^2 + cap_f_t_coefficients[5] * cwt * ecwt) * rated_capacity` - get the given capacity: `given_capacity = capacity_validation_pts_dict[dict_key]` - - add the given capacity to the given_capacities dictionary: `given_capacities[[cwt,ecwt]] = given_capacity` + - add the given capacity to the given_capacities dictionary: `given_capacities[dict_key] = given_capacity` - Compare the expected capacity to the given capacity. This should not be an exact match, but with a margin of error (see notes at the bottom for suggested margins of errors). We don't need to do anything if the capacities match, but if they don't match we need to add the conditions to the non_matching_capacity_validation_points list: `if expected_capacity != given_capacity: non_matching_capacity_validation_points.append({"CWT": cwt, "ECWT": ecwt})` - otherwise this value doesn't exist, append these conditions to the missing_capacity_validation_points list: `else: missing_capacity_validation_points.append({"CWT": cwt, "ECWT": ecwt})` @@ -67,12 +68,13 @@ J-6 - create a list of missing power validation points: `missing_power_validation_points = []` - loop through the expected_cwt_temps: `for cwt in expected_cwt_temps:` - loop through each expected_ect_temps: `for ecwt in expected_ecwt_temps:` - - look for the power validation points in power_validation_pts_dict: `if power_validation_pts_dict[[cwt, ecwt]]:` + - create the key: `dict_key = f"{cwt}, {ecwt}"` + - look for the power validation points in power_validation_pts_dict: `if power_validation_pts_dict[dict_key]:` - we are expecting to see multiple validation points aligning with the expected_validation_plr. Create a list of part load ratios that are given. Later we'll compare this with the expected list to make sure that all points are given: `given_plrs = []` - - look at each power validation point in the list: `for power_validation_point_result in power_validation_pts_dict[[cwt, ecwt]]:` + - look at each power validation point in the list: `for power_validation_point_result in power_validation_pts_dict[dict_key]:` - get the load: `load = power_validation_point.load` - get the given power: `given_power = power_validation_point_result` - - calculate the PLR by dividing the load by the given capacity at these operating conditions: `plr = load / given_capacities[[cwt, ecwt]]` + - calculate the PLR by dividing the load by the given capacity at these operating conditions: `plr = load / given_capacities[dict_key]` - check whether the plr is one of the plrs that we need to check - note to dev team, please accept a match that is with 0.01 of the expected: `if plr in expected_validation_plr:` - add the plr to the list of plrs provided: `given_plrs.append(plr)` - calculate eir_plr using the coefficients given: `eir_plr = plr_coefficients[0] + plr_coefficients[1] * plr + plr_coefficients[2] * plr^2` @@ -80,7 +82,7 @@ J-6 - calculate the expected power using the formula: - Chiller operating power = Rated Capacity × CAP-f-T × EIR-f-T × EIR-f-PLR × Chiller Input Power at Rated Conditions/Chiller Capacity at Rated Conditions - in this case, the given capacity under these operating conditions is the rated capacity * cap_ft, so the modified formula is as follows: - - `expected_power = given_capacity[[cwt, ecwt]] * eir_ft * eir_plr * rated_power/rated_capacity` + - `expected_power = given_capacity[dict_key] * eir_ft * eir_plr * rated_power/rated_capacity` - check whether the expected power and the given power are equal. This should not be an exact match, but with a margin of error (see notes at the bottom for suggested margins of errors). If the expected power and given power do not match, add the conditions to the non_matching_power_validation_points list: `if expected_power != given_power: non_matching_power_validation_points.append({"CWT": cwt, "ECWT": ecwt, "PLR": plr})` - otherwise, this particular plr is not given, append these conditions to the missing_power_validation_points list: `missing_power_validation_points.append({"CWT": cwt, "ECWT": ecwt, "PLR": plr})` - otherwise, this point isn't given, append these conditions to the missing_power_validation_points list: `missing_power_validation_points.append({"CWT": cwt, "ECWT": ecwt, "PLR": "ALL"})` From 6ecd056a8d008507aa5f7983333525b625f0b01a Mon Sep 17 00:00:00 2001 From: KarenWGard <114143532+KarenWGard@users.noreply.github.com> Date: Wed, 18 Dec 2024 14:14:51 -0500 Subject: [PATCH 8/8] Update Rule22-42.md --- docs/section22/Rule22-42.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/section22/Rule22-42.md b/docs/section22/Rule22-42.md index ee74843e21..e3e5a3c3cf 100644 --- a/docs/section22/Rule22-42.md +++ b/docs/section22/Rule22-42.md @@ -31,7 +31,7 @@ J-6 - continue if the curve set is not "NONE" - the curve set could be none if the chiller.compressor_type is not one of the recognized types for Appendix G: `if curve_set <> "NONE":` - calculate the chiller rated power by dividing the chiller rated capacity by the chiller full load efficiency (cop): `rated_power = chiller.rated_capacity / chiller.full_load_efficiency` - create a list of the expected capacity validation points - this is in 25% intervals, starting with 0.25 to 1: `expected_validation_plr = [0.25,0.5,0.75,1]` - - create a list of the expected temperatures for the chilled water temperature for the validation calculations - expected_cwt_temps - units are (F). The values are selected to capture the minimum, maximum, rating condition and some points in between: `expected_cwt_temps = [39,45,50,55]` + - create a list of the expected temperatures for the chilled water temperature for the validation calculations - expected_chwt_temps - units are (F). The values are selected to capture the minimum, maximum, rating condition and some points in between: `expected_chwt_temps = [39,45,50,55]` - create a list of the expected entering condenser temperatures for the condenser water temperature for the validation calculations - expected_ecwt_temps - units are (F). The values are selected to capture the minimum, maximum, rating condition and some points in between: `expected_ecwt_temps = [60,104,85,72.5,97.5]` - get the coefficients for the EIR-f-T curve (IP units) using a table lookup for table J-6. This assumes that the lookup function will return a list with the coefficients in order (C1,C2,...): `eir_f_t_coefficients = table_J_6_lookup(curve_set,"EIR-f-T")` @@ -47,45 +47,45 @@ J-6 - look at each value in chiller.power_validation_points: `for power_validation_point in chiller.power_validation_points:` - create the key: `dict_key = f"{power_validation_point.chilled_water_supply_temperature}, {power_validation_point.condenser_temperature}"` - set the default to a blank list: `power_validation_pts_dict.setdefault([dict_key], [])` - - append the power validation point to the list at this given: `power_validation_pts_dict[dict_key].append(power_validation_point.result)` + - append the power validation point to the list at this given: `power_validation_pts_dict[dict_key].append(power_validation_point)` - create a dictionary of the expected capacities for use in the power validation check: `given_capacities = {}` - the following lines or logic do the capacity validation check: - create a list of non-matching capacity validation points: `non_matching_capacity_validation_points = []` - create a list of missing capacity validation points: `missing_capacity_validation_points = []` - - loop through the expected_cwt_temps: `for cwt in expected_cwt_temps:` + - loop through the expected_chwt_temps: `for chwt in expected_chwt_temps:` - loop through each expected_ecwt_temps: `for ecwt in expected_ecwt_temps:` - - create the key: `dict_key = f"{cwt}, {ecwt}"` + - create the key: `dict_key = f"{chwt}, {ecwt}"` - look for the capacity validation point in capacity_validation_pts_dict: `if capacity_validation_pts_dict[dict_key]:` - - calculate the expected capacity by multiplying the result of the formula by the rated_capacity: `expected_capacity = (cap_f_t_coefficients[0] + cap_f_t_coefficients[1] * cwt + cap_f_t_coefficients[2] * cwt^2 + cap_f_t_coefficients[3] * ecwt + cap_f_t_coefficients[4] * ecwt^2 + cap_f_t_coefficients[5] * cwt * ecwt) * rated_capacity` + - calculate the expected capacity by multiplying the result of the formula by the rated_capacity: `expected_capacity = (cap_f_t_coefficients[0] + cap_f_t_coefficients[1] * chwt + cap_f_t_coefficients[2] * chwt^2 + cap_f_t_coefficients[3] * ecwt + cap_f_t_coefficients[4] * ecwt^2 + cap_f_t_coefficients[5] * chwt * ecwt) * rated_capacity` - get the given capacity: `given_capacity = capacity_validation_pts_dict[dict_key]` - add the given capacity to the given_capacities dictionary: `given_capacities[dict_key] = given_capacity` - - Compare the expected capacity to the given capacity. This should not be an exact match, but with a margin of error (see notes at the bottom for suggested margins of errors). We don't need to do anything if the capacities match, but if they don't match we need to add the conditions to the non_matching_capacity_validation_points list: `if expected_capacity != given_capacity: non_matching_capacity_validation_points.append({"CWT": cwt, "ECWT": ecwt})` - - otherwise this value doesn't exist, append these conditions to the missing_capacity_validation_points list: `else: missing_capacity_validation_points.append({"CWT": cwt, "ECWT": ecwt})` + - Compare the expected capacity to the given capacity. This should not be an exact match, but with a margin of error (see notes at the bottom for suggested margins of errors). We don't need to do anything if the capacities match, but if they don't match we need to add the conditions to the non_matching_capacity_validation_points list: `if expected_capacity != given_capacity: non_matching_capacity_validation_points.append({"CHWT": chwt, "ECWT": ecwt})` + - otherwise this value doesn't exist, append these conditions to the missing_capacity_validation_points list: `else: missing_capacity_validation_points.append({"CHWT": chwt, "ECWT": ecwt})` - the following lines or logic do the power validation check: - create a list of non-matching power validation points: `non_matching_power_validation_points = []` - create a list of missing power validation points: `missing_power_validation_points = []` - - loop through the expected_cwt_temps: `for cwt in expected_cwt_temps:` + - loop through the expected_chwt_temps: `for chwt in expected_chwt_temps:` - loop through each expected_ect_temps: `for ecwt in expected_ecwt_temps:` - - create the key: `dict_key = f"{cwt}, {ecwt}"` + - create the key: `dict_key = f"{chwt}, {ecwt}"` - look for the power validation points in power_validation_pts_dict: `if power_validation_pts_dict[dict_key]:` - we are expecting to see multiple validation points aligning with the expected_validation_plr. Create a list of part load ratios that are given. Later we'll compare this with the expected list to make sure that all points are given: `given_plrs = []` - - look at each power validation point in the list: `for power_validation_point_result in power_validation_pts_dict[dict_key]:` + - look at each power validation point in the list: `for power_validation_point in power_validation_pts_dict[dict_key]:` - get the load: `load = power_validation_point.load` - - get the given power: `given_power = power_validation_point_result` + - get the given power: `given_power = power_validation_point.result` - calculate the PLR by dividing the load by the given capacity at these operating conditions: `plr = load / given_capacities[dict_key]` - check whether the plr is one of the plrs that we need to check - note to dev team, please accept a match that is with 0.01 of the expected: `if plr in expected_validation_plr:` - add the plr to the list of plrs provided: `given_plrs.append(plr)` - calculate eir_plr using the coefficients given: `eir_plr = plr_coefficients[0] + plr_coefficients[1] * plr + plr_coefficients[2] * plr^2` - - calculate the eir_ft using the coefficients given: `eir_ft = eir_f_t_coefficients[0] + eir_f_t_coefficients[1] * cwt + eir_f_t_coefficients[2] * cwt^2 + eir_f_t_coefficients[3] * ecwt + eir_f_t_coefficients[4] * ecwt^2 + eir_f_t_coefficients[5] * cwt * ecwt` + - calculate the eir_ft using the coefficients given: `eir_ft = eir_f_t_coefficients[0] + eir_f_t_coefficients[1] * chwt + eir_f_t_coefficients[2] * chwt^2 + eir_f_t_coefficients[3] * ecwt + eir_f_t_coefficients[4] * ecwt^2 + eir_f_t_coefficients[5] * chwt * ecwt` - calculate the expected power using the formula: - Chiller operating power = Rated Capacity × CAP-f-T × EIR-f-T × EIR-f-PLR × Chiller Input Power at Rated Conditions/Chiller Capacity at Rated Conditions - in this case, the given capacity under these operating conditions is the rated capacity * cap_ft, so the modified formula is as follows: - `expected_power = given_capacity[dict_key] * eir_ft * eir_plr * rated_power/rated_capacity` - - check whether the expected power and the given power are equal. This should not be an exact match, but with a margin of error (see notes at the bottom for suggested margins of errors). If the expected power and given power do not match, add the conditions to the non_matching_power_validation_points list: `if expected_power != given_power: non_matching_power_validation_points.append({"CWT": cwt, "ECWT": ecwt, "PLR": plr})` - - otherwise, this particular plr is not given, append these conditions to the missing_power_validation_points list: `missing_power_validation_points.append({"CWT": cwt, "ECWT": ecwt, "PLR": plr})` - - otherwise, this point isn't given, append these conditions to the missing_power_validation_points list: `missing_power_validation_points.append({"CWT": cwt, "ECWT": ecwt, "PLR": "ALL"})` + - check whether the expected power and the given power are equal. This should not be an exact match, but with a margin of error (see notes at the bottom for suggested margins of errors). If the expected power and given power do not match, add the conditions to the non_matching_power_validation_points list: `if expected_power != given_power: non_matching_power_validation_points.append({"CHWT": chwt, "ECWT": ecwt, "PLR": plr})` + - otherwise, this particular plr is not given, append these conditions to the missing_power_validation_points list: `missing_power_validation_points.append({"CHWT": chwt, "ECWT": ecwt, "PLR": plr})` + - otherwise, this point isn't given, append these conditions to the missing_power_validation_points list: `missing_power_validation_points.append({"CHWT": chwt, "ECWT": ecwt, "PLR": "ALL"})` **Rule Assertion:** - Case 1: all lists of missing or non-matching validation points have a length of zero: PASS: `if len(non_matching_capacity_validation_points) == len(missing_capacity_validation_points) == len(non_matching_power_validation_points) == len(missing_power_validation_points) == 0: PASS`