Skip to content

Commit

Permalink
Merge pull request #64 from pnnl/VAV_Minimum_Turndown_During_Reheat_P…
Browse files Browse the repository at this point in the history
…ressure_Reset

Develop VAVMinimumTurndownDuringReheatPressureReset
  • Loading branch information
yunjoonjung-PNNL authored Dec 6, 2024
2 parents 3cb76dc + af87493 commit 23c40a1
Show file tree
Hide file tree
Showing 5 changed files with 320 additions and 4 deletions.
2 changes: 2 additions & 0 deletions constrain/library/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from .vav_static_pressure_sensor_location import *
from .vav_minimum_turndown_during_reheat import *
from .vav_turndown_during_reheat import *
from .vav_minimum_turndown_during_reheat_pressure_reset import *
from .ventilation_fan_controls import *
from .wlhp_loop_heat_rejection_controls import *
from .supply_air_temp_reset import *
Expand Down Expand Up @@ -71,6 +72,7 @@
"VAVStaticPressureSensorLocation",
"VAVMinimumTurndownDuringReheat",
"VAVTurndownDuringReheat",
"VAVMinimumTurndownDuringReheatPressureReset",
"VentilationFanControl",
"WLHPLoopHeatRejectionControl",
"SupplyAirTempReset",
Expand Down
4 changes: 4 additions & 0 deletions constrain/library/vav_minimum_turndown_during_reheat.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,8 @@ def vav_turndown_check(self, data):
return "Untested"

def verify(self):
if (self.df["V_dot_VAV_max"] != 0).all():
self.df["V_dot_ratio"] = (
self.df["V_dot_VAV"] / self.df["V_dot_VAV_max"]
) # for plotting
self.result = self.df.apply(lambda d: self.vav_turndown_check(d), axis=1)
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
"""
### Description
When a VAV box is in reheat mode, the ratio of VAV airflow rate to VAV max airflow rate must not be greater than the min design turndown ratio and the pressure setpoint must remain the same
### Code requirement
- Code Name: ASHRAE 90.1
- Code Year: 2016
- Code Section: 6.5.2 Simultaneous Heating and Cooling Limitation
- Code Subsection: 6.5.2.1 Zone Controls
### Verification Approach
- We aim to identify how VAV airflow rate varies when the VAV box is and isn't in reheat mode.
### Verification logic
```
if reheat_coil_flag:
if V_dot_VAV_max == 0
Untested
if V_dot_VAV_max > 0.0 and V_dot_VAV / V_dot_VAV_max > VAV_min_turndown_design + turndown_tol
if P_set_prev is None:
return Untested
elif abs(P_set - P_set_prev) > P_set_tol:
return Untested
else:
return False
else
Untested
```
### Data requirements
- reheat_coil_flag: VAV box reheat coil operation status
- V_dot_VAV: actual VAV volume flow
- V_dot_VAV_max: max VAV volume flow
- VAV_min_turndown_design: design VAV box min turndown ratio
- P_set: duct pressure setpoint
- turndown_tol: VAV turndown tolerance
- P_set_tol: pressure setpoint tolerance
"""

import numpy as np
from constrain.checklib import RuleCheckBase


class VAVMinimumTurndownDuringReheatPressureReset(RuleCheckBase):
points = [
"reheat_coil_flag",
"V_dot_VAV",
"V_dot_VAV_max",
"VAV_min_turndown_design",
"P_set",
"turndown_tol",
"P_set_tol",
]

def vav_turndown_check(self, data):
if data["reheat_coil_flag"]:
if data["V_dot_VAV_max"] == 0:
return "Untested"
elif (
data["V_dot_VAV"] / data["V_dot_VAV_max"]
> data["VAV_min_turndown_design"] + data["turndown_tol"]
):
if data["P_set_prev"] is None:
return "Untested"
elif abs(data["P_set"] - data["P_set_prev"]) > data["P_set_tol"]:
return "Untested"
else:
return False
else:
return True
else:
return "Untested"

def verify(self):
# Copy the previous row's value in 'P_set' column to the current row
self.df["P_set_prev"] = self.df["P_set"].shift(1).replace({np.nan: None})
if (self.df["V_dot_VAV_max"] != 0).all():
self.df["V_dot_ratio"] = (
self.df["V_dot_VAV"] / self.df["V_dot_VAV_max"]
) # for plotting
self.result = self.df.apply(lambda d: self.vav_turndown_check(d), axis=1)
43 changes: 39 additions & 4 deletions schema/library.json
Original file line number Diff line number Diff line change
Expand Up @@ -1576,19 +1576,54 @@
"assertions_type": "pass",
"description_assertions": [
"if reheat_coil_flag:",
" if V_dot_VAV_max == 0",
" if V_dot_VAV_max == 0:",
" Untested",
" if V_dot_VAV_max > 0.0 and V_dot_VAV / V_dot_VAV_max > VAV_min_turndown_design + turndown_tol",
" if V_dot_VAV_max > 0.0 and V_dot_VAV / V_dot_VAV_max > VAV_min_turndown_design + turndown_tol:",
" fail",
" else:",
" pass",
"else",
"else: ",
" Untested",
"end"
]
},
"VAVTurndownDuringReheat": {
"VAVMinimumTurndownDuringReheatPressureReset": {
"library_item_id": 69,
"description_brief": "When a VAV box is in reheat mode, the ratio of VAV airflow rate to VAV max airflow rate must not be greater than the min design turndown ratio and the pressure setpoint must remain the same",
"description_index": [
"Section 6.5.2.1 ASHRAE 90.1-2016"
],
"description_datapoints": {
"reheat_coil_flag": "VAV box reheat coil operation status",
"V_dot_VAV": "VAV airflow rate",
"V_dot_VAV_max": "VAV max airflow rate",
"VAV_min_turndown_design": "design VAV box min turndown ratio",
"P_set": "duct pressure setpoint",
"turndown_tol": "VAV turndown tolerance",
"P_set_tol": "pressure setpoint tolerance"
},
"description_verification_type": "rule-based",
"assertions_type": "pass",
"description_assertions": [
"if reheat_coil_flag:",
" if V_dot_VAV_max == 0:",
" Untested",
" if V_dot_VAV_max > 0.0 and V_dot_VAV / V_dot_VAV_max > VAV_min_turndown_design + turndown_tol:",
" if P_set_prev is None:",
" Untested",
" elif abs(P_set - P_set_prev) > P_set_tol:",
" Untested",
" else:",
" fail",
" else:",
" pass",
"else: ",
" Untested",
"end"
]
},
"VAVTurndownDuringReheat": {
"library_item_id": 70,
"description_brief": "When a VAV box is in reheat mode, the ratio of V_dot_VAV to V_dot_VAV_max should be higher than when it isn't in reheat mode",
"description_index": [
"Section 6.5.2.1 ASHRAE 90.1-2016"
Expand Down
193 changes: 193 additions & 0 deletions tests/test_vav_minimum_turndown_during_reheat_pressure_reset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
import sys
import unittest

sys.path.append("./constrain")
import datetime

import pandas as pd
from lib_unit_test_runner import *


class TestVAVTurndown(unittest.TestCase):
def test_vav_turndown_reheat_coil_flag_untested(self):
points = [
"reheat_coil_flag",
"V_dot_VAV",
"V_dot_VAV_max",
"VAV_min_turndown_design",
"P_set",
"turndown_tol",
"P_set_tol",
]

timestamp = [
datetime(2024, 8, 1, 12, 0, 0),
datetime(2024, 8, 1, 13, 0, 0),
]

data = [
[False, 0.005, 0.01, 0.3, 1.0, 0.01, 0.01],
[False, 0.005, 0.01, 0.3, 1.1, 0.01, 0.01],
]

df = pd.DataFrame(data, columns=points, index=timestamp)

verification_obj = run_test_verification_with_data(
"VAVMinimumTurndownDuringReheatPressureReset", df
)
results = list(verification_obj.result)
expected_results = [
"Untested",
"Untested",
]

self.assertEqual(results, expected_results)
self.assertEqual(verification_obj.check_bool(), "Untested")

def test_vav_turndown_V_dot_max_zero_untested(self):
points = [
"reheat_coil_flag",
"V_dot_VAV",
"V_dot_VAV_max",
"VAV_min_turndown_design",
"P_set",
"turndown_tol",
"P_set_tol",
]

timestamp = [
datetime(2024, 8, 1, 12, 0, 0),
datetime(2024, 8, 1, 13, 0, 0),
]

data = [
[True, 0.005, 0.0, 0.3, 1.0, 0.01, 0.01],
[True, 0.005, 0.0, 0.3, 1.1, 0.01, 0.01],
]

df = pd.DataFrame(data, columns=points, index=timestamp)

verification_obj = run_test_verification_with_data(
"VAVMinimumTurndownDuringReheatPressureReset", df
)
results = list(verification_obj.result)
expected_results = [
"Untested",
"Untested",
]

self.assertEqual(results, expected_results)
self.assertEqual(verification_obj.check_bool(), "Untested")

def test_vav_turndown_P_set_same_untested(self):
points = [
"reheat_coil_flag",
"V_dot_VAV",
"V_dot_VAV_max",
"VAV_min_turndown_design",
"P_set",
"turndown_tol",
"P_set_tol",
]

timestamp = [
datetime(2024, 8, 1, 12, 0, 0),
datetime(2024, 8, 1, 13, 0, 0),
]

data = [
[True, 0.005, 0.0, 0.3, 1.0, 0.01, 0.01],
[True, 0.005, 0.0, 0.3, 1.0, 0.01, 0.01],
]

df = pd.DataFrame(data, columns=points, index=timestamp)

verification_obj = run_test_verification_with_data(
"VAVMinimumTurndownDuringReheatPressureReset", df
)
results = list(verification_obj.result)
expected_results = [
"Untested",
"Untested",
]

self.assertEqual(results, expected_results)
self.assertEqual(verification_obj.check_bool(), "Untested")

def test_vav_turndown_pass(self):
points = [
"reheat_coil_flag",
"V_dot_VAV",
"V_dot_VAV_max",
"VAV_min_turndown_design",
"P_set",
"turndown_tol",
"P_set_tol",
]

timestamp = [
datetime(2024, 8, 1, 12, 0, 0),
datetime(2024, 8, 1, 13, 0, 0),
]

data = [
[True, 0.005, 0.06, 0.3, 1.0, 0.01, 0.01],
[True, 0.005, 0.06, 0.3, 1.1, 0.01, 0.01],
]

df = pd.DataFrame(data, columns=points, index=timestamp)

verification_obj = run_test_verification_with_data(
"VAVMinimumTurndownDuringReheatPressureReset", df
)

results = pd.Series(list(verification_obj.result))
expected_results = pd.Series(
[
True,
True,
]
)
self.assertTrue(results.equals(expected_results))

binary_result = verification_obj.check_bool()
self.assertTrue(binary_result)

def test_vav_turndown_fail(self):
points = [
"reheat_coil_flag",
"V_dot_VAV",
"V_dot_VAV_max",
"VAV_min_turndown_design",
"P_set",
"turndown_tol",
"P_set_tol",
]

timestamp = [
datetime(2024, 8, 1, 12, 0, 0),
datetime(2024, 8, 1, 13, 0, 0),
]

data = [
[True, 0.005, 0.01, 0.3, 1.0, 0.01, 0.01],
[True, 0.005, 0.01, 0.3, 1.0, 0.01, 0.01],
]

df = pd.DataFrame(data, columns=points, index=timestamp)

verification_obj = run_test_verification_with_data(
"VAVMinimumTurndownDuringReheatPressureReset", df
)

results = pd.Series(list(verification_obj.result))
expected_results = pd.Series(
[
"Untested",
False,
]
)
self.assertTrue(results.equals(expected_results))

binary_result = verification_obj.check_bool()
self.assertFalse(binary_result)

0 comments on commit 23c40a1

Please sign in to comment.