first commit
This commit is contained in:
0
test/calculators/ballast/__init__.py
Normal file
0
test/calculators/ballast/__init__.py
Normal file
122
test/calculators/ballast/ballast_and_tray_count_test.py
Normal file
122
test/calculators/ballast/ballast_and_tray_count_test.py
Normal file
@@ -0,0 +1,122 @@
|
||||
import unittest
|
||||
from unittest.mock import MagicMock
|
||||
from nose.tools import eq_
|
||||
|
||||
from helix.calculators.ballast_calculator import BallastCalculator
|
||||
from helix.constants.module_type import ModuleType
|
||||
from helix.constants.panel_type import PanelType
|
||||
from helix.constants.system_type import SystemType
|
||||
|
||||
|
||||
class BallastAndTrayCountTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.values = MagicMock()
|
||||
self.system_type = SystemType.singleTilt
|
||||
self.module_type = ModuleType.Cell128
|
||||
self.values.system_type.return_value = self.system_type
|
||||
self.values.module_system_constants.return_value = self.system_type.module_constants(self.module_type)
|
||||
|
||||
self.subject = BallastCalculator(self.values)
|
||||
self.panel_type = PanelType.EastWest
|
||||
self.ballast_block_weight = 20
|
||||
self.anchor_count = 0
|
||||
|
||||
def test_no_ballast(self):
|
||||
self.force_to_resist = 0
|
||||
result = self.subject.ballast_and_tray_count(self.force_to_resist, self.panel_type, self.ballast_block_weight, self.anchor_count)
|
||||
|
||||
eq_(result.ballast_count, 0)
|
||||
eq_(result.link_tray_count, 0)
|
||||
eq_(result.cross_tray_count, 0)
|
||||
eq_(result.system_weight, 69.75)
|
||||
eq_(result.needs_anchor, False)
|
||||
|
||||
def test_ballast_no_trays(self):
|
||||
self.force_to_resist = 140
|
||||
result = self.subject.ballast_and_tray_count(self.force_to_resist, self.panel_type, self.ballast_block_weight, self.anchor_count)
|
||||
|
||||
eq_(result.ballast_count, 4)
|
||||
eq_(result.link_tray_count, 0)
|
||||
eq_(result.cross_tray_count, 0)
|
||||
eq_(result.system_weight, 69.75)
|
||||
eq_(result.needs_anchor, False)
|
||||
|
||||
def test_ballast_and_link_trays(self):
|
||||
self.force_to_resist = 230
|
||||
result = self.subject.ballast_and_tray_count(self.force_to_resist, self.panel_type, self.ballast_block_weight, self.anchor_count)
|
||||
|
||||
eq_(result.ballast_count, 8)
|
||||
eq_(result.link_tray_count, 1)
|
||||
eq_(result.cross_tray_count, 0)
|
||||
eq_(result.system_weight, 72.05)
|
||||
eq_(result.needs_anchor, False)
|
||||
|
||||
def test_ballast_and_oscillate_between_0_and_1_link_trays(self):
|
||||
self.force_to_resist = 210
|
||||
result = self.subject.ballast_and_tray_count(self.force_to_resist, self.panel_type, self.ballast_block_weight, self.anchor_count)
|
||||
|
||||
eq_(result.ballast_count, 7)
|
||||
eq_(result.link_tray_count, 1)
|
||||
eq_(result.cross_tray_count, 0)
|
||||
eq_(result.system_weight, 72.05)
|
||||
eq_(result.needs_anchor, False)
|
||||
|
||||
def test_ballast_and_link_tray_and_cross_tray(self):
|
||||
self.force_to_resist = 390
|
||||
result = self.subject.ballast_and_tray_count(self.force_to_resist, self.panel_type, self.ballast_block_weight, self.anchor_count)
|
||||
|
||||
eq_(result.ballast_count, 16)
|
||||
eq_(result.link_tray_count, 1)
|
||||
eq_(result.cross_tray_count, 1)
|
||||
eq_(result.system_weight, 75.23)
|
||||
eq_(result.needs_anchor, False)
|
||||
|
||||
def test_ballast_and_link_tray_and_oscillate_between_0_and_1_cross_trays(self):
|
||||
self.force_to_resist = 330
|
||||
result = self.subject.ballast_and_tray_count(self.force_to_resist, self.panel_type, self.ballast_block_weight, self.anchor_count)
|
||||
|
||||
eq_(result.ballast_count, 13)
|
||||
eq_(result.link_tray_count, 1)
|
||||
eq_(result.cross_tray_count, 0)
|
||||
eq_(result.system_weight, 72.05)
|
||||
eq_(result.needs_anchor, False)
|
||||
|
||||
def test_ballast_and_link_tray_and_2_cross_trays(self):
|
||||
self.force_to_resist = 570
|
||||
result = self.subject.ballast_and_tray_count(self.force_to_resist, self.panel_type, self.ballast_block_weight, self.anchor_count)
|
||||
|
||||
eq_(result.ballast_count, 25)
|
||||
eq_(result.link_tray_count, 1)
|
||||
eq_(result.cross_tray_count, 2)
|
||||
eq_(result.system_weight, 78.41)
|
||||
eq_(result.needs_anchor, False)
|
||||
|
||||
def test_ballast_and_link_tray_and_at_first_2_then_1_cross_trays(self):
|
||||
self.force_to_resist = 515
|
||||
result = self.subject.ballast_and_tray_count(self.force_to_resist, self.panel_type, self.ballast_block_weight, self.anchor_count)
|
||||
|
||||
eq_(result.ballast_count, 22)
|
||||
eq_(result.link_tray_count, 1)
|
||||
eq_(result.cross_tray_count, 1)
|
||||
eq_(result.system_weight, 75.23)
|
||||
eq_(result.needs_anchor, False)
|
||||
|
||||
def test_ballast_and_all_trays_and_anchor(self):
|
||||
self.force_to_resist = 770
|
||||
result = self.subject.ballast_and_tray_count(self.force_to_resist, self.panel_type, self.ballast_block_weight, self.anchor_count)
|
||||
|
||||
eq_(result.ballast_count, 35)
|
||||
eq_(result.link_tray_count, 1)
|
||||
eq_(result.cross_tray_count, 2)
|
||||
eq_(result.system_weight, 78.41)
|
||||
eq_(result.needs_anchor, True)
|
||||
|
||||
def test_ballast_and_all_trays_and_at_first_anchor_then_no_anchor(self):
|
||||
self.force_to_resist = 675
|
||||
result = self.subject.ballast_and_tray_count(self.force_to_resist, self.panel_type, self.ballast_block_weight, self.anchor_count)
|
||||
|
||||
eq_(result.ballast_count, 30)
|
||||
eq_(result.link_tray_count, 1)
|
||||
eq_(result.cross_tray_count, 2)
|
||||
eq_(result.system_weight, 78.41)
|
||||
eq_(result.needs_anchor, False)
|
||||
@@ -0,0 +1,252 @@
|
||||
import unittest
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from nose.tools import assert_almost_equal, eq_
|
||||
from numpy import array
|
||||
from numpy.testing import assert_array_equal
|
||||
|
||||
from helix.calculators.ballast_calculator import BallastCalculator
|
||||
from helix.constants.anchor_type import AnchorType
|
||||
from helix.constants.module_type import ModuleType
|
||||
from helix.constants.panel_type import PanelType
|
||||
from helix.constants.system_type import SystemType
|
||||
from helix.models.panel import Panel, PanelWarnings
|
||||
from test.test_helpers import assert_array_is_close
|
||||
|
||||
|
||||
class BallastCalculatorWhenDualTiltAnd128CellTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.values = MagicMock()
|
||||
"""
|
||||
Generated using site parameters:
|
||||
height: 100
|
||||
length: 1000
|
||||
width: 1500
|
||||
parapet: 0
|
||||
wind_speed: 110
|
||||
exposure_category: D
|
||||
"""
|
||||
self.c_p_matrix = array([[0.751977, 0.656898, 0.662582, 0.570086],
|
||||
[0.568747, 0.491495, 0.496113, 0.420960],
|
||||
[0.352521, 0.304321, 0.307202, 0.260312],
|
||||
[0.197385, 0.171634, 0.173174, 0.148123],
|
||||
[0.060000, 0.050000, 0.052000, 0.039000]
|
||||
])
|
||||
self.system_type = SystemType.dualTilt
|
||||
self.module_type = ModuleType.Cell128
|
||||
self.values.max_system_pressure.return_value = 100
|
||||
self.values.system_type.return_value = self.system_type
|
||||
self.values.anchor_type.return_value = AnchorType.OMG_PowerGrip
|
||||
self.values.module_system_constants.return_value = self.system_type.module_constants(self.module_type)
|
||||
self.q_z = 37.72825742
|
||||
self.subject = BallastCalculator(self.values)
|
||||
|
||||
def test_summary_table(self):
|
||||
self.values.ballast_block_weight.return_value = 20
|
||||
self.values.max_system_pressure.return_value = 17
|
||||
|
||||
expected_value = {
|
||||
PanelType.Corner: {
|
||||
'anchors': [3, 2, 0, 0, 0],
|
||||
'ballast blocks': [15, 14, 25, 12, 0],
|
||||
'pressure': ['8.14', '7.74', '12.11', '6.88', '2.12']
|
||||
},
|
||||
PanelType.NorthSouth: {
|
||||
'anchors': [3, 2, 0, 0, 0],
|
||||
'ballast blocks': [7, 8, 22, 10, 0],
|
||||
'pressure': ['4.90', '5.29', '10.83', '6.05', '2.10']
|
||||
},
|
||||
PanelType.EastWest: {
|
||||
'anchors': [3, 2, 0, 0, 0],
|
||||
'ballast blocks': [8, 8, 22, 10, 0],
|
||||
'pressure': ['5.25', '5.25', '10.78', '5.97', '2.02']
|
||||
},
|
||||
PanelType.Middle: {
|
||||
'anchors': [2, 0, 0, 0, 0],
|
||||
'ballast blocks': [15, 32, 18, 8, 0],
|
||||
'pressure': ['8.02', '14.73', '9.13', '5.17', '1.99']
|
||||
},
|
||||
}
|
||||
|
||||
received_table = self.subject.summary_table(self.c_p_matrix, self.q_z)
|
||||
eq_(received_table.keys(), expected_value.keys())
|
||||
for key in expected_value.keys():
|
||||
received_table[key].pop('warnings')
|
||||
self.assertDictEqual(received_table[key], expected_value[key])
|
||||
# Because the above is way more explicit than simply 'eq_(received_table, expected_value)'
|
||||
|
||||
def test_ballast_and_trays_matrix(self):
|
||||
raw_data = [
|
||||
Panel(wind_zone=2, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=2, panel_type=PanelType.NorthSouth),
|
||||
Panel(wind_zone=4, panel_type=PanelType.EastWest),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Middle),
|
||||
Panel(wind_zone=3, panel_type=PanelType.NorthSouth),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Corner)
|
||||
]
|
||||
self.values.ballast_block_weight.return_value = 20
|
||||
|
||||
expected_value = [
|
||||
Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=25, link_tray=2, cross_tray=2, wind_anchors=0,
|
||||
pressure=12.11),
|
||||
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=22, link_tray=2, cross_tray=1, wind_anchors=0,
|
||||
pressure=10.83),
|
||||
Panel(wind_zone=4, panel_type=PanelType.EastWest, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0,
|
||||
pressure=2.02),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=15, link_tray=2, cross_tray=1, wind_anchors=3,
|
||||
pressure=8.14),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=32, link_tray=2, cross_tray=3, wind_anchors=0,
|
||||
pressure=14.73),
|
||||
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=10, link_tray=1, cross_tray=0, wind_anchors=0,
|
||||
pressure=6.05),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Corner, ballast=44, link_tray=2, cross_tray=4, wind_anchors=0,
|
||||
pressure=19.65)
|
||||
]
|
||||
|
||||
assert_array_is_close(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, raw_data),
|
||||
expected_value, decimal=2)
|
||||
|
||||
def test_ballast_and_trays_matrix_ups_ballast_for_fuzzy_wind_zone(self):
|
||||
raw_data = [
|
||||
Panel(wind_zone=2, panel_type=PanelType.Corner, fuzzy_wind_zone=True),
|
||||
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, fuzzy_wind_zone=True),
|
||||
Panel(wind_zone=4, panel_type=PanelType.EastWest, fuzzy_wind_zone=True),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner, fuzzy_wind_zone=True),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Middle, fuzzy_wind_zone=True),
|
||||
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, fuzzy_wind_zone=True),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Corner, fuzzy_wind_zone=True)
|
||||
]
|
||||
self.values.ballast_block_weight.return_value = 20
|
||||
|
||||
expected_value = [
|
||||
Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=30, link_tray=2, cross_tray=2, wind_anchors=0,
|
||||
pressure=14.06, fuzzy_wind_zone=True),
|
||||
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=25, link_tray=2, cross_tray=2, wind_anchors=0,
|
||||
pressure=12.06, fuzzy_wind_zone=True),
|
||||
Panel(wind_zone=4, panel_type=PanelType.EastWest, ballast=1, link_tray=0, cross_tray=0, wind_anchors=0,
|
||||
pressure=2.41, fuzzy_wind_zone=True),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=10, link_tray=2, cross_tray=1, wind_anchors=4,
|
||||
pressure=6.18, fuzzy_wind_zone=True, warnings=[PanelWarnings.MaxPsf]),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=37, link_tray=2, cross_tray=4, wind_anchors=0,
|
||||
pressure=16.75, fuzzy_wind_zone=True),
|
||||
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=12, link_tray=2, cross_tray=0, wind_anchors=0,
|
||||
pressure=6.86, fuzzy_wind_zone=True),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Corner, ballast=7, link_tray=2, cross_tray=0, wind_anchors=3,
|
||||
pressure=4.93, fuzzy_wind_zone=True)
|
||||
]
|
||||
|
||||
assert_array_is_close(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, raw_data),
|
||||
expected_value, decimal=2)
|
||||
|
||||
def test_update_ballast(self):
|
||||
self.values.ballast_block_weight.return_value = 20
|
||||
self.values.max_system_pressure.return_value = 17
|
||||
|
||||
panels = [
|
||||
Panel(wind_zone=2, panel_type=PanelType.Corner, wind_anchors=0, seismic_anchors=1),
|
||||
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1),
|
||||
Panel(wind_zone=4, panel_type=PanelType.EastWest, wind_anchors=0, seismic_anchors=1),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner, wind_anchors=3, seismic_anchors=0),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Middle, wind_anchors=0, seismic_anchors=1),
|
||||
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Corner, wind_anchors=2, seismic_anchors=0)
|
||||
]
|
||||
|
||||
expected = [
|
||||
Panel(wind_zone=2, panel_type=PanelType.Corner, wind_anchors=0, seismic_anchors=1,
|
||||
ballast=11, link_tray=2, cross_tray=0, pressure=6.49),
|
||||
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1,
|
||||
ballast=6, link_tray=1, cross_tray=0, pressure=4.49),
|
||||
Panel(wind_zone=4, panel_type=PanelType.EastWest, wind_anchors=0, seismic_anchors=1,
|
||||
ballast=0, link_tray=0, cross_tray=0, pressure=2.02),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner, wind_anchors=3, seismic_anchors=0,
|
||||
ballast=15, link_tray=2, cross_tray=1, pressure=8.14),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Middle, wind_anchors=0, seismic_anchors=1,
|
||||
ballast=17, link_tray=2, cross_tray=2, pressure=8.81),
|
||||
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1,
|
||||
ballast=0, link_tray=0, cross_tray=0, pressure=2.10),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Corner, wind_anchors=2, seismic_anchors=0,
|
||||
ballast=14, link_tray=2, cross_tray=1, pressure=7.74),
|
||||
]
|
||||
|
||||
result = self.subject.update_ballast(self.c_p_matrix, self.q_z, panels)
|
||||
assert_array_is_close(result, expected, decimal=2)
|
||||
|
||||
def test_presented_link_trays(self):
|
||||
panels = [
|
||||
Panel(panel_type=PanelType.Corner, link_tray=2),
|
||||
Panel(panel_type=PanelType.NorthSouth, link_tray=2),
|
||||
Panel(panel_type=PanelType.EastWest, link_tray=0),
|
||||
Panel(panel_type=PanelType.Corner, link_tray=2),
|
||||
Panel(panel_type=PanelType.Middle, link_tray=2),
|
||||
Panel(panel_type=PanelType.NorthSouth, link_tray=1),
|
||||
Panel(panel_type=PanelType.Corner, link_tray=2),
|
||||
]
|
||||
|
||||
expected = [
|
||||
Panel(presented_link_tray=2, panel_type=PanelType.Corner, link_tray=2),
|
||||
Panel(presented_link_tray=2, panel_type=PanelType.NorthSouth, link_tray=2),
|
||||
Panel(presented_link_tray=1, panel_type=PanelType.EastWest, link_tray=0),
|
||||
Panel(presented_link_tray=2, panel_type=PanelType.Corner, link_tray=2),
|
||||
Panel(presented_link_tray=1, panel_type=PanelType.Middle, link_tray=2),
|
||||
Panel(presented_link_tray=2, panel_type=PanelType.NorthSouth, link_tray=1),
|
||||
Panel(presented_link_tray=2, panel_type=PanelType.Corner, link_tray=2)
|
||||
]
|
||||
|
||||
assert_array_equal(self.subject.show_presented_link_trays(panels), expected)
|
||||
|
||||
def test_pressure_exceeeding_max_system_pressure(self):
|
||||
self.values.ballast_block_weight.return_value = 20
|
||||
self.values.max_system_pressure.return_value = 17
|
||||
|
||||
panel_data = [
|
||||
Panel(wind_zone=2, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=2, panel_type=PanelType.NorthSouth),
|
||||
Panel(wind_zone=4, panel_type=PanelType.EastWest),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Middle),
|
||||
Panel(wind_zone=3, panel_type=PanelType.NorthSouth),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Corner)
|
||||
]
|
||||
|
||||
expected_value = [
|
||||
Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=25, link_tray=2, cross_tray=2, wind_anchors=0, pressure=12.11),
|
||||
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=22, link_tray=2, cross_tray=1, wind_anchors=0, pressure=10.83),
|
||||
Panel(wind_zone=4, panel_type=PanelType.EastWest, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, pressure=2.02),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=15, link_tray=2, cross_tray=1, wind_anchors=3, pressure=8.14),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=32, link_tray=2, cross_tray=3, wind_anchors=0, pressure=14.73),
|
||||
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=10, link_tray=1, cross_tray=0, wind_anchors=0, pressure=6.05),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Corner, ballast=14, link_tray=2, cross_tray=1, wind_anchors=2, pressure=7.74)
|
||||
]
|
||||
|
||||
assert_array_is_close(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, panel_data), expected_value, decimal=2)
|
||||
|
||||
def test_ballast_count_when_base_weight_greater_than_uplift(self):
|
||||
expected = Panel(wind_zone=4, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, pressure=1.99)
|
||||
assert self.subject.ballast_tray_and_anchor_count(4, PanelType.Middle, 14, 100, self.c_p_matrix, self.q_z).almost_equal(expected, decimal=2)
|
||||
|
||||
def test_individual_ballast_block_uplift_greater_than_base_weight(self):
|
||||
expected = Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=21, link_tray=2, cross_tray=2, wind_anchors=2, pressure=7.91)
|
||||
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Middle, 14, 100, self.c_p_matrix, self.q_z).almost_equal(expected, decimal=2)
|
||||
|
||||
expected = Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=15, link_tray=2, cross_tray=2, wind_anchors=2, pressure=8.02)
|
||||
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Middle, 20, 100, self.c_p_matrix, self.q_z).almost_equal(expected, decimal=2)
|
||||
|
||||
def test_ballast_blocks_exceeding_tray_capacity(self):
|
||||
expected = Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=24, link_tray=2, cross_tray=3, wind_anchors=2, pressure=7.85)
|
||||
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Middle, 12, 100, self.c_p_matrix, self.q_z).almost_equal(expected, decimal=2)
|
||||
|
||||
def test_when_max_system_pressure_is_lower_than_base_weight_pressure(self):
|
||||
max_system_pressure = 0
|
||||
expected = Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=3, pressure=1.99)
|
||||
|
||||
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Middle, 12, max_system_pressure, self.c_p_matrix, self.q_z).almost_equal(
|
||||
expected,
|
||||
decimal=2)
|
||||
|
||||
def test_uplift(self):
|
||||
assert_almost_equal(self.subject.uplift(0.62717, self.q_z), 1102.2, 1)
|
||||
|
||||
def test_calculate_single_unit_pressure_on_roof(self):
|
||||
assert_almost_equal(self.subject.calculate_pressure_on_roof(78, 12, 105.23), 20.3417625, 6)
|
||||
@@ -0,0 +1,245 @@
|
||||
import unittest
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from nose.tools import assert_almost_equal, eq_
|
||||
from numpy import array
|
||||
from numpy.testing import assert_array_equal
|
||||
|
||||
from helix.calculators.ballast_calculator import BallastCalculator
|
||||
from helix.constants.anchor_type import AnchorType
|
||||
from helix.constants.module_type import ModuleType
|
||||
from helix.constants.panel_type import PanelType
|
||||
from helix.constants.system_type import SystemType
|
||||
from helix.models.panel import Panel
|
||||
from test.test_helpers import assert_array_is_close
|
||||
|
||||
|
||||
class BallastCalculatorWhenDualTiltAnd96CellTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.values = MagicMock()
|
||||
"""
|
||||
Generated using site parameters:
|
||||
height: 100
|
||||
length: 1000
|
||||
width: 1500
|
||||
parapet: 0
|
||||
wind_speed: 110
|
||||
exposure_category: D
|
||||
"""
|
||||
self.c_p_matrix = array([[0.7800, 0.70, 0.68, 0.546],
|
||||
[0.5949, 0.52, 0.51, 0.400],
|
||||
[0.3700, 0.32, 0.32, 0.250],
|
||||
[0.2100, 0.18, 0.18, 0.140],
|
||||
[0.0600, 0.05, 0.05, 0.040]])
|
||||
self.system_type = SystemType.dualTilt
|
||||
self.module_type = ModuleType.Cell96
|
||||
self.values.max_system_pressure.return_value = 100
|
||||
self.values.system_type.return_value = self.system_type
|
||||
self.values.module_type.return_value = self.module_type
|
||||
self.values.anchor_type.return_value = AnchorType.OMG_PowerGrip
|
||||
self.values.module_system_constants.return_value = self.system_type.module_constants(self.module_type)
|
||||
self.q_z = 37.729
|
||||
self.subject = BallastCalculator(self.values)
|
||||
|
||||
def test_summary_table(self):
|
||||
self.values.ballast_block_weight.return_value = 20
|
||||
self.values.max_system_pressure.return_value = 17
|
||||
|
||||
expected_value = {
|
||||
PanelType.Corner: {
|
||||
'anchors': [3, 2, 0, 0, 0],
|
||||
'ballast blocks': [2, 5, 20, 10, 0],
|
||||
'pressure': ['3.48', '5.03', '12.90', '7.62', '2.40']
|
||||
},
|
||||
PanelType.NorthSouth: {
|
||||
'anchors': [2, 1, 0, 0, 0],
|
||||
'ballast blocks': [11, 15, 17, 8, 0],
|
||||
'pressure': ['8.24', '10.32', '11.35', '6.59', '2.40']
|
||||
},
|
||||
PanelType.EastWest: {
|
||||
'anchors': [2, 1, 0, 0, 0],
|
||||
'ballast blocks': [10, 14, 17, 8, 0],
|
||||
'pressure': ['7.55', '9.63', '11.18', '6.46', '2.26']
|
||||
},
|
||||
PanelType.Middle: {
|
||||
'anchors': [2, 0, 0, 0, 0],
|
||||
'ballast blocks': [2, 22, 12, 5, 0],
|
||||
'pressure': ['3.34', '13.83', '8.59', '4.85', '2.26']
|
||||
},
|
||||
}
|
||||
|
||||
received_table = self.subject.summary_table(self.c_p_matrix, self.q_z)
|
||||
eq_(received_table.keys(), expected_value.keys())
|
||||
for key in expected_value.keys():
|
||||
received_table[key].pop('warnings')
|
||||
self.assertDictEqual(received_table[key], expected_value[key])
|
||||
# Because the above is way more explicit than simply 'eq_(received_table, expected_value)'
|
||||
|
||||
def test_ballast_and_trays_matrix(self):
|
||||
panels = [
|
||||
Panel(wind_zone=2, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=2, panel_type=PanelType.NorthSouth),
|
||||
Panel(wind_zone=4, panel_type=PanelType.EastWest),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Middle),
|
||||
Panel(wind_zone=3, panel_type=PanelType.NorthSouth),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Corner),
|
||||
]
|
||||
|
||||
self.values.ballast_block_weight.return_value = 20
|
||||
|
||||
# Ballast, link tray, cross tray, anchor count, psf
|
||||
expected_value = [
|
||||
Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=20, link_tray=2, cross_tray=1, wind_anchors=0, pressure=12.90),
|
||||
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=17, link_tray=2, cross_tray=1, wind_anchors=0, pressure=11.35),
|
||||
Panel(wind_zone=4, panel_type=PanelType.EastWest, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, pressure=2.26),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=47, link_tray=2, cross_tray=4, wind_anchors=0, pressure=27.07),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=22, link_tray=2, cross_tray=2, wind_anchors=0, pressure=13.82),
|
||||
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=8, link_tray=1, cross_tray=0, wind_anchors=0, pressure=6.59),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Corner, ballast=35, link_tray=2, cross_tray=3, wind_anchors=0, pressure=20.79)
|
||||
]
|
||||
|
||||
assert_array_is_close(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, panels), expected_value, decimal=2)
|
||||
|
||||
def test_update_ballast(self):
|
||||
self.values.ballast_block_weight.return_value = 20
|
||||
self.values.max_system_pressure.return_value = 17
|
||||
|
||||
panels = [
|
||||
Panel(wind_zone=2, panel_type=PanelType.Corner, wind_anchors=0, seismic_anchors=1),
|
||||
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1),
|
||||
Panel(wind_zone=4, panel_type=PanelType.EastWest, wind_anchors=0, seismic_anchors=1),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner, wind_anchors=3, seismic_anchors=0),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Middle, wind_anchors=0, seismic_anchors=1),
|
||||
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Corner, wind_anchors=2, seismic_anchors=0)
|
||||
]
|
||||
|
||||
expected_value = [
|
||||
Panel(wind_zone=2, panel_type=PanelType.Corner, wind_anchors=0, seismic_anchors=1, ballast=5, link_tray=0, cross_tray=0, pressure=4.99),
|
||||
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1, ballast=2, link_tray=0, cross_tray=0, pressure=3.43),
|
||||
Panel(wind_zone=4, panel_type=PanelType.EastWest, wind_anchors=0, seismic_anchors=1, ballast=0, link_tray=0, cross_tray=0, pressure=2.26),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner, wind_anchors=3, seismic_anchors=0, ballast=2, link_tray=1, cross_tray=0, pressure=3.48),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Middle, wind_anchors=0, seismic_anchors=1, ballast=7, link_tray=2, cross_tray=0, pressure=5.94),
|
||||
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1, ballast=0, link_tray=0, cross_tray=0, pressure=2.40),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Corner, wind_anchors=2, seismic_anchors=0, ballast=5, link_tray=1, cross_tray=0, pressure=5.03)
|
||||
]
|
||||
|
||||
result = self.subject.update_ballast(self.c_p_matrix, self.q_z, panels)
|
||||
assert_array_is_close(result, expected_value, decimal=2)
|
||||
|
||||
def test_update_ballast_with_fuzzy_wind_zone(self):
|
||||
self.values.ballast_block_weight.return_value = 20
|
||||
self.values.max_system_pressure.return_value = 17
|
||||
|
||||
panels = [
|
||||
Panel(wind_zone=2, panel_type=PanelType.Corner, wind_anchors=0, seismic_anchors=1, fuzzy_wind_zone=True),
|
||||
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1, fuzzy_wind_zone=True),
|
||||
Panel(wind_zone=4, panel_type=PanelType.EastWest, wind_anchors=0, seismic_anchors=1, fuzzy_wind_zone=True),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner, wind_anchors=3, seismic_anchors=0, fuzzy_wind_zone=True),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Middle, wind_anchors=0, seismic_anchors=1, fuzzy_wind_zone=True),
|
||||
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1, fuzzy_wind_zone=True),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Corner, wind_anchors=2, seismic_anchors=0, fuzzy_wind_zone=True)
|
||||
]
|
||||
|
||||
expected_value = [
|
||||
Panel(wind_zone=2, panel_type=PanelType.Corner, wind_anchors=0, seismic_anchors=1, ballast=9, link_tray=2, cross_tray=0, pressure=7.15, fuzzy_wind_zone=True),
|
||||
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1, ballast=5, link_tray=0, cross_tray=0, pressure=4.99, fuzzy_wind_zone=True),
|
||||
Panel(wind_zone=4, panel_type=PanelType.EastWest, wind_anchors=0, seismic_anchors=1, ballast=0, link_tray=0, cross_tray=0, pressure=2.26, fuzzy_wind_zone=True),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner, wind_anchors=3, seismic_anchors=0, ballast=9, link_tray=2, cross_tray=0, pressure=7.15, fuzzy_wind_zone=True),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Middle, wind_anchors=0, seismic_anchors=1, ballast=11, link_tray=2, cross_tray=1, pressure=8.07, fuzzy_wind_zone=True),
|
||||
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1, ballast=0, link_tray=0, cross_tray=0, pressure=2.40, fuzzy_wind_zone=True),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Corner, wind_anchors=2, seismic_anchors=0, ballast=11, link_tray=2, cross_tray=0, pressure=8.18, fuzzy_wind_zone=True)
|
||||
]
|
||||
|
||||
result = self.subject.update_ballast(self.c_p_matrix, self.q_z, panels)
|
||||
assert_array_is_close(result, expected_value, decimal=2)
|
||||
|
||||
def test_presented_link_trays(self):
|
||||
panels = [
|
||||
Panel(panel_type=PanelType.Corner, link_tray=2),
|
||||
Panel(panel_type=PanelType.NorthSouth, link_tray=2),
|
||||
Panel(panel_type=PanelType.EastWest, link_tray=0),
|
||||
Panel(panel_type=PanelType.Corner, link_tray=2),
|
||||
Panel(panel_type=PanelType.Middle, link_tray=2),
|
||||
Panel(panel_type=PanelType.NorthSouth, link_tray=1),
|
||||
Panel(panel_type=PanelType.Corner, link_tray=2)
|
||||
]
|
||||
expected_value = [
|
||||
Panel(presented_link_tray=2, panel_type=PanelType.Corner, link_tray=2),
|
||||
Panel(presented_link_tray=2, panel_type=PanelType.NorthSouth, link_tray=2),
|
||||
Panel(presented_link_tray=1, panel_type=PanelType.EastWest, link_tray=0),
|
||||
Panel(presented_link_tray=2, panel_type=PanelType.Corner, link_tray=2),
|
||||
Panel(presented_link_tray=1, panel_type=PanelType.Middle, link_tray=2),
|
||||
Panel(presented_link_tray=2, panel_type=PanelType.NorthSouth, link_tray=1),
|
||||
Panel(presented_link_tray=2, panel_type=PanelType.Corner, link_tray=2)
|
||||
]
|
||||
|
||||
assert_array_equal(self.subject.show_presented_link_trays(panels), expected_value)
|
||||
|
||||
def test_pressure_exceeeding_max_system_pressure(self):
|
||||
self.values.ballast_block_weight.return_value = 20
|
||||
self.values.max_system_pressure.return_value = 17
|
||||
|
||||
panels = [
|
||||
Panel(wind_zone=2, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=2, panel_type=PanelType.NorthSouth),
|
||||
Panel(wind_zone=4, panel_type=PanelType.EastWest),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Middle),
|
||||
Panel(wind_zone=3, panel_type=PanelType.NorthSouth),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Corner)
|
||||
]
|
||||
|
||||
expected_value = [
|
||||
Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=20, link_tray=2, cross_tray=1, wind_anchors=0, pressure=12.90),
|
||||
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=17, link_tray=2, cross_tray=1, wind_anchors=0, pressure=11.35),
|
||||
Panel(wind_zone=4, panel_type=PanelType.EastWest, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, pressure=2.26),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=2, link_tray=1, cross_tray=0, wind_anchors=3, pressure=3.48),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=22, link_tray=2, cross_tray=2, wind_anchors=0, pressure=13.83),
|
||||
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=8, link_tray=1, cross_tray=0, wind_anchors=0, pressure=6.59),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Corner, ballast=5, link_tray=1, cross_tray=0, wind_anchors=2, pressure=5.03)
|
||||
]
|
||||
|
||||
assert_array_is_close(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, panels), expected_value, decimal=2)
|
||||
|
||||
def test_ballast_count_when_base_weight_greater_than_uplift(self):
|
||||
assert self.subject.ballast_tray_and_anchor_count(4, PanelType.Middle, 14, 100, self.c_p_matrix,
|
||||
self.q_z).almost_equal(
|
||||
Panel(wind_zone=4, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, pressure=2.26),
|
||||
decimal=2)
|
||||
|
||||
def test_individual_ballast_block_uplift_greater_than_base_weight(self):
|
||||
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Middle, 14, 100, self.c_p_matrix,
|
||||
self.q_z).almost_equal(
|
||||
Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=45, link_tray=2, cross_tray=4, wind_anchors=0, pressure=18.87),
|
||||
decimal=2)
|
||||
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Middle, 20, 100, self.c_p_matrix,
|
||||
self.q_z).almost_equal(
|
||||
Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=32, link_tray=2, cross_tray=3, wind_anchors=0, pressure=19.07),
|
||||
decimal=2)
|
||||
|
||||
def test_ballast_blocks_exceeding_tray_capacity(self):
|
||||
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Middle, 12, 100, self.c_p_matrix,
|
||||
self.q_z).almost_equal(
|
||||
Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=3, link_tray=1, cross_tray=0, wind_anchors=2, pressure=3.23),
|
||||
decimal=2)
|
||||
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Corner, 12, 100, self.c_p_matrix,
|
||||
self.q_z).almost_equal(
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=3, link_tray=1, cross_tray=0, wind_anchors=3, pressure=3.37),
|
||||
decimal=2)
|
||||
|
||||
def test_when_max_system_pressure_is_lower_than_base_weight_pressure(self):
|
||||
max_system_pressure = 0
|
||||
expected = Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0,
|
||||
wind_anchors=3, pressure=2.26)
|
||||
|
||||
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Middle, 12,
|
||||
max_system_pressure, self.c_p_matrix, self.q_z).almost_equal(expected, decimal=2)
|
||||
|
||||
|
||||
def test_uplift(self):
|
||||
assert_almost_equal(self.subject.uplift(0.62717, self.q_z), 831.50, 1)
|
||||
|
||||
def test_calculate_single_unit_pressure_on_roof(self):
|
||||
assert_almost_equal(self.subject.calculate_pressure_on_roof(78, 12, 105.23), 26.96, 2)
|
||||
@@ -0,0 +1,306 @@
|
||||
import unittest
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from nose.tools import assert_almost_equal, eq_
|
||||
from numpy import array
|
||||
from numpy.testing import assert_array_equal
|
||||
|
||||
from helix.calculators.ballast_calculator import BallastCalculator
|
||||
from helix.constants.anchor_type import AnchorType
|
||||
from helix.constants.module_type import ModuleType
|
||||
from helix.constants.panel_type import PanelType
|
||||
from helix.constants.system_type import SystemType
|
||||
from helix.models.panel import Panel, PanelWarnings
|
||||
from test.test_helpers import assert_array_is_close
|
||||
|
||||
|
||||
class BallastCalculatorWhenDualTiltAndPSeriesTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.values = MagicMock()
|
||||
"""
|
||||
Generated using site parameters:
|
||||
height: 100
|
||||
length: 1000
|
||||
width: 1500
|
||||
parapet: 0
|
||||
wind_speed: 110
|
||||
exposure_category: D
|
||||
"""
|
||||
self.c_p_matrix = array([[0.964647, 0.843638, 0.850871, 0.733149],
|
||||
[0.730023, 0.631703, 0.637580, 0.541930],
|
||||
[0.452508, 0.391163, 0.394830, 0.335151],
|
||||
[0.253272, 0.220498, 0.222457, 0.190574],
|
||||
[0.060000, 0.050000, 0.052000, 0.039000]])
|
||||
|
||||
self.system_type = SystemType.dualTilt
|
||||
self.module_type = ModuleType.PSeries
|
||||
self.values.max_system_pressure.return_value = 100
|
||||
self.values.system_type.return_value = self.system_type
|
||||
self.values.anchor_type.return_value = AnchorType.OMG_PowerGrip
|
||||
self.values.module_system_constants.return_value = self.system_type.module_constants(self.module_type)
|
||||
self.q_z = 37.72825742
|
||||
self.subject = BallastCalculator(self.values)
|
||||
|
||||
def test_summary_table(self):
|
||||
self.values.ballast_block_weight.return_value = 20
|
||||
self.values.max_system_pressure.return_value = 17
|
||||
|
||||
expected_value = {
|
||||
PanelType.Corner: {
|
||||
'anchors': [4, 3, 0, 0, 0],
|
||||
'ballast blocks': [15, 10, 33, 16, 0],
|
||||
'pressure': ['8.43', '6.38', '15.93', '8.83', '2.12']
|
||||
},
|
||||
PanelType.NorthSouth: {
|
||||
'anchors': [4, 3, 0, 0, 0],
|
||||
'ballast blocks': [5, 2, 28, 14, 0],
|
||||
'pressure': ['4.22', '2.97', '13.77', '7.90', '2.10']
|
||||
},
|
||||
PanelType.EastWest: {
|
||||
'anchors': [4, 3, 0, 0, 0],
|
||||
'ballast blocks': [6, 3, 28, 14, 0],
|
||||
'pressure': ['4.58', '3.29', '13.72', '7.86', '2.01']
|
||||
},
|
||||
PanelType.Middle: {
|
||||
'anchors': [3, 2, 0, 0, 0],
|
||||
'ballast blocks': [11, 10, 23, 11, 0],
|
||||
'pressure': ['6.61', '6.20', '11.59', '6.61', '1.99']
|
||||
},
|
||||
}
|
||||
|
||||
received_table = self.subject.summary_table(self.c_p_matrix, self.q_z)
|
||||
eq_(received_table.keys(), expected_value.keys())
|
||||
for key in expected_value.keys():
|
||||
received_table[key].pop('warnings')
|
||||
self.assertDictEqual(received_table[key], expected_value[key])
|
||||
# Because the above is way more explicit than simply 'eq_(received_table, expected_value)'
|
||||
|
||||
def test_summary_table_when_special_small_building(self):
|
||||
"""
|
||||
Generated using site parameters:
|
||||
height: 15
|
||||
length: 100
|
||||
width: 100
|
||||
parapet: 0
|
||||
wind_speed: 110
|
||||
exposure_category: B
|
||||
"""
|
||||
self.c_p_matrix = array([[0.277131, 0.182052, 0.187735, 0.129774],
|
||||
[0.182934, 0.115506, 0.118940, 0.084465],
|
||||
[0.111800, 0.075909, 0.077290, 0.066873],
|
||||
[0.068781, 0.050000, 0.052000, 0.039068],
|
||||
[0.060000, 0.050000, 0.052000, 0.039000]])
|
||||
|
||||
self.system_type = SystemType.dualTilt
|
||||
self.module_type = ModuleType.PSeries
|
||||
self.values.max_system_pressure.return_value = 8
|
||||
self.values.ballast_block_weight.return_value = 16
|
||||
self.values.system_type.return_value = self.system_type
|
||||
self.values.anchor_type.return_value = AnchorType.OMG_PowerGrip
|
||||
self.values.module_system_constants.return_value = self.system_type.module_constants(self.module_type)
|
||||
self.q_z = 18.43072
|
||||
self.subject = BallastCalculator(self.values)
|
||||
|
||||
expected_value = {
|
||||
PanelType.Corner: {
|
||||
'anchors': [0, 0, 0, 0, 0],
|
||||
'ballast blocks': [8, 3, 0, 0, 0],
|
||||
'pressure': ['4.79', '3.11', '2.12', '2.12', '2.12']
|
||||
},
|
||||
PanelType.NorthSouth: {
|
||||
'anchors': [0, 0, 0, 0, 0],
|
||||
'ballast blocks': [3, 0, 0, 0, 0],
|
||||
'pressure': ['3.08', '2.10', '2.10', '2.10', '2.10']
|
||||
},
|
||||
PanelType.EastWest: {
|
||||
'anchors': [0, 0, 0, 0, 0],
|
||||
'ballast blocks': [4, 0, 0, 0, 0],
|
||||
'pressure': ['3.32', '2.01', '2.01', '2.01', '2.01']
|
||||
},
|
||||
PanelType.Middle: {
|
||||
'anchors': [0, 0, 0, 0, 0],
|
||||
'ballast blocks': [1, 0, 0, 0, 0],
|
||||
'pressure': ['2.32', '1.99', '1.99', '1.99', '1.99']
|
||||
},
|
||||
}
|
||||
|
||||
received_table = self.subject.summary_table(self.c_p_matrix, self.q_z)
|
||||
eq_(received_table.keys(), expected_value.keys())
|
||||
for key in expected_value.keys():
|
||||
received_table[key].pop('warnings')
|
||||
self.assertDictEqual(received_table[key], expected_value[key])
|
||||
|
||||
def test_ballast_and_trays_matrix(self):
|
||||
raw_data = [
|
||||
Panel(wind_zone=2, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=2, panel_type=PanelType.NorthSouth),
|
||||
Panel(wind_zone=4, panel_type=PanelType.EastWest),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Middle),
|
||||
Panel(wind_zone=3, panel_type=PanelType.NorthSouth),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Corner)
|
||||
]
|
||||
self.values.ballast_block_weight.return_value = 20
|
||||
|
||||
expected_value = [
|
||||
Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=33, link_tray=2, cross_tray=3, wind_anchors=0,
|
||||
pressure=15.93),
|
||||
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=28, link_tray=2, cross_tray=2, wind_anchors=0,
|
||||
pressure=13.77),
|
||||
Panel(wind_zone=4, panel_type=PanelType.EastWest, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0,
|
||||
pressure=2.01),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=15, link_tray=2, cross_tray=1, wind_anchors=4,
|
||||
pressure=8.43, warnings=[PanelWarnings.MaxPsf]),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=40, link_tray=2, cross_tray=4, wind_anchors=0,
|
||||
pressure=18.68),
|
||||
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=14, link_tray=2, cross_tray=0, wind_anchors=0,
|
||||
pressure=7.90),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Corner, ballast=10, link_tray=2, cross_tray=1, wind_anchors=3,
|
||||
pressure=6.38),
|
||||
]
|
||||
|
||||
assert_array_is_close(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, raw_data),
|
||||
expected_value, decimal=2)
|
||||
|
||||
def test_update_ballast(self):
|
||||
self.values.ballast_block_weight.return_value = 20
|
||||
self.values.max_system_pressure.return_value = 17
|
||||
|
||||
panels = [
|
||||
Panel(wind_zone=2, panel_type=PanelType.Corner, wind_anchors=0, seismic_anchors=1),
|
||||
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1),
|
||||
Panel(wind_zone=4, panel_type=PanelType.EastWest, wind_anchors=0, seismic_anchors=1),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner, wind_anchors=4, seismic_anchors=0),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Middle, wind_anchors=0, seismic_anchors=1),
|
||||
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Corner, wind_anchors=3, seismic_anchors=0)
|
||||
]
|
||||
|
||||
expected = [
|
||||
Panel(wind_zone=2, panel_type=PanelType.Corner, wind_anchors=0, seismic_anchors=1,
|
||||
ballast=18, link_tray=2, cross_tray=1, pressure=9.65),
|
||||
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1,
|
||||
ballast=13, link_tray=2, cross_tray=0, pressure=7.50),
|
||||
Panel(wind_zone=4, panel_type=PanelType.EastWest, wind_anchors=0, seismic_anchors=1,
|
||||
ballast=0, link_tray=0, cross_tray=0, pressure=2.01),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner, wind_anchors=4, seismic_anchors=0,
|
||||
ballast=15, link_tray=2, cross_tray=1, pressure=8.43),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Middle, wind_anchors=0, seismic_anchors=1,
|
||||
ballast=25, link_tray=2, cross_tray=3, pressure=12.47),
|
||||
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, wind_anchors=0, seismic_anchors=1,
|
||||
ballast=0, link_tray=0, cross_tray=0, pressure=2.10),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Corner, wind_anchors=3, seismic_anchors=0,
|
||||
ballast=10, link_tray=2, cross_tray=1, pressure=6.38),
|
||||
]
|
||||
|
||||
result = self.subject.update_ballast(self.c_p_matrix, self.q_z, panels)
|
||||
assert_array_is_close(result, expected, decimal=2)
|
||||
|
||||
def test_presented_link_trays(self):
|
||||
panels = [
|
||||
Panel(panel_type=PanelType.Corner, link_tray=2),
|
||||
Panel(panel_type=PanelType.NorthSouth, link_tray=2),
|
||||
Panel(panel_type=PanelType.EastWest, link_tray=0),
|
||||
Panel(panel_type=PanelType.Corner, link_tray=2),
|
||||
Panel(panel_type=PanelType.Middle, link_tray=2),
|
||||
Panel(panel_type=PanelType.NorthSouth, link_tray=1),
|
||||
Panel(panel_type=PanelType.Corner, link_tray=2),
|
||||
]
|
||||
|
||||
expected = [
|
||||
Panel(presented_link_tray=2, panel_type=PanelType.Corner, link_tray=2),
|
||||
Panel(presented_link_tray=2, panel_type=PanelType.NorthSouth, link_tray=2),
|
||||
Panel(presented_link_tray=1, panel_type=PanelType.EastWest, link_tray=0),
|
||||
Panel(presented_link_tray=2, panel_type=PanelType.Corner, link_tray=2),
|
||||
Panel(presented_link_tray=1, panel_type=PanelType.Middle, link_tray=2),
|
||||
Panel(presented_link_tray=2, panel_type=PanelType.NorthSouth, link_tray=1),
|
||||
Panel(presented_link_tray=2, panel_type=PanelType.Corner, link_tray=2)
|
||||
]
|
||||
|
||||
assert_array_equal(self.subject.show_presented_link_trays(panels), expected)
|
||||
|
||||
def test_pressure_exceeeding_max_system_pressure(self):
|
||||
self.values.ballast_block_weight.return_value = 20
|
||||
self.values.max_system_pressure.return_value = 17
|
||||
|
||||
panel_data = [
|
||||
Panel(wind_zone=2, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=2, panel_type=PanelType.NorthSouth),
|
||||
Panel(wind_zone=4, panel_type=PanelType.EastWest),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Middle),
|
||||
Panel(wind_zone=3, panel_type=PanelType.NorthSouth),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Corner)
|
||||
]
|
||||
|
||||
expected_value = [
|
||||
Panel(wind_zone=2, panel_type=PanelType.Corner, ballast=33, link_tray=2, cross_tray=3, wind_anchors=0, pressure=15.93),
|
||||
Panel(wind_zone=2, panel_type=PanelType.NorthSouth, ballast=28, link_tray=2, cross_tray=2, wind_anchors=0, pressure=13.77),
|
||||
Panel(wind_zone=4, panel_type=PanelType.EastWest, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, pressure=2.01),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=15, link_tray=2, cross_tray=1, wind_anchors=4, pressure=8.43, warnings=[PanelWarnings.MaxPsf]),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Middle, ballast=10, link_tray=2, cross_tray=1, wind_anchors=2, pressure=6.20),
|
||||
Panel(wind_zone=3, panel_type=PanelType.NorthSouth, ballast=14, link_tray=2, cross_tray=0, wind_anchors=0, pressure=7.90),
|
||||
Panel(wind_zone=1, panel_type=PanelType.Corner, ballast=10, link_tray=2, cross_tray=1, wind_anchors=3, pressure=6.38)
|
||||
]
|
||||
|
||||
assert_array_is_close(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, panel_data), expected_value, decimal=2)
|
||||
|
||||
def test_ballast_count_when_special_small_building(self):
|
||||
"""
|
||||
Generated using site parameters:
|
||||
height: 15
|
||||
length: 100
|
||||
width: 100
|
||||
parapet: 0
|
||||
wind_speed: 110
|
||||
exposure_category: B
|
||||
|
||||
"""
|
||||
self.c_p_matrix = array([[0.277131, 0.182052, 0.187735, 0.129774],
|
||||
[0.182934, 0.115506, 0.118940, 0.084465],
|
||||
[0.111800, 0.075909, 0.077290, 0.066873],
|
||||
[0.068781, 0.050000, 0.052000, 0.039068],
|
||||
[0.060000, 0.050000, 0.052000, 0.039000]])
|
||||
|
||||
self.system_type = SystemType.dualTilt
|
||||
self.module_type = ModuleType.PSeries
|
||||
self.values.max_system_pressure.return_value = 8
|
||||
self.values.ballast_block_weight.return_value = 16
|
||||
self.values.system_type.return_value = self.system_type
|
||||
self.values.anchor_type.return_value = AnchorType.OMG_PowerGrip
|
||||
self.values.module_system_constants.return_value = self.system_type.module_constants(self.module_type)
|
||||
self.q_z = 18.43072
|
||||
self.subject = BallastCalculator(self.values)
|
||||
|
||||
expected = Panel(wind_zone=0, panel_type=PanelType.NorthSouth, ballast=3, link_tray=0, cross_tray=0, wind_anchors=0, pressure=3.08)
|
||||
received = self.subject.ballast_tray_and_anchor_count(0, PanelType.NorthSouth, 16, 8, self.c_p_matrix, self.q_z)
|
||||
assert received.almost_equal(expected, decimal=2)
|
||||
|
||||
def test_ballast_count_when_base_weight_greater_than_uplift(self):
|
||||
expected = Panel(wind_zone=4, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=0, pressure=1.99)
|
||||
assert self.subject.ballast_tray_and_anchor_count(4, PanelType.Middle, 14, 100, self.c_p_matrix, self.q_z).almost_equal(expected, decimal=2)
|
||||
|
||||
def test_individual_ballast_block_uplift_greater_than_base_weight(self):
|
||||
expected = Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=15, link_tray=2, cross_tray=2, wind_anchors=3, pressure=6.47)
|
||||
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Middle, 14, 100, self.c_p_matrix, self.q_z).almost_equal(expected, decimal=2)
|
||||
|
||||
expected = Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=11, link_tray=2, cross_tray=1, wind_anchors=3, pressure=6.61)
|
||||
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Middle, 20, 100, self.c_p_matrix, self.q_z).almost_equal(expected, decimal=2)
|
||||
|
||||
def test_ballast_blocks_exceeding_tray_capacity(self):
|
||||
expected = Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=18, link_tray=2, cross_tray=2, wind_anchors=3, pressure=6.59)
|
||||
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Middle, 12, 100, self.c_p_matrix, self.q_z).almost_equal(expected, decimal=2)
|
||||
|
||||
def test_when_max_system_pressure_is_lower_than_base_weight_pressure(self):
|
||||
max_system_pressure = 0
|
||||
expected = Panel(wind_zone=0, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0, wind_anchors=4, pressure=1.99)
|
||||
|
||||
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Middle, 12, max_system_pressure, self.c_p_matrix, self.q_z).almost_equal(
|
||||
expected,
|
||||
decimal=2)
|
||||
|
||||
def test_uplift(self):
|
||||
assert_almost_equal(self.subject.uplift(0.62717, self.q_z), 1051.54, 1)
|
||||
|
||||
def test_calculate_single_unit_pressure_on_roof(self):
|
||||
assert_almost_equal(self.subject.calculate_pressure_on_roof(78, 12, 105.23), 21.3213163825, 6)
|
||||
@@ -0,0 +1,270 @@
|
||||
import unittest
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from nose.tools import assert_almost_equal, eq_
|
||||
from numpy import array
|
||||
from numpy.testing import assert_array_equal
|
||||
|
||||
from helix.calculators.ballast_calculator import BallastCalculator
|
||||
from helix.constants.anchor_type import AnchorType
|
||||
from helix.constants.module_type import ModuleType
|
||||
from helix.constants.panel_type import PanelType
|
||||
from helix.constants.system_type import SystemType
|
||||
from helix.models.panel import Panel, PanelWarnings
|
||||
from test.test_helpers import assert_array_is_close
|
||||
|
||||
|
||||
class BallastCalculatorWhenSingleTiltAnd128CellTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.values = MagicMock()
|
||||
"""
|
||||
Generated using site parameters:
|
||||
height: 100
|
||||
length: 1000
|
||||
width: 1500
|
||||
parapet: 0
|
||||
wind_speed: 150
|
||||
exposure_category: D
|
||||
"""
|
||||
|
||||
self.c_p_matrix = array([[1.464330, 1.334027, 1.111689, 1.079155],
|
||||
[1.152100, 1.046580, 0.872150, 0.845805],
|
||||
[0.660541, 0.610771, 0.436265, 0.425614],
|
||||
[0.663595, 0.595406, 0.425290, 0.410697],
|
||||
[0.446503, 0.269616, 0.404423, 0.261210],
|
||||
[0.425368, 0.384182, 0.295525, 0.286033],
|
||||
[0.201015, 0.184521, 0.184521, 0.179580],
|
||||
[0.542408, 0.486253, 0.486253, 0.469428],
|
||||
[1.487760, 1.301254, 1.301254, 1.245374],
|
||||
[0.888854, 0.789797, 0.394899, 0.380059],
|
||||
[0.172217, 0.151210, 0.108007, 0.103511]])
|
||||
self.system_type = SystemType.singleTilt
|
||||
self.module_type = ModuleType.Cell128
|
||||
self.values.max_system_pressure.return_value = 1000
|
||||
self.values.system_type.return_value = self.system_type
|
||||
self.values.anchor_type.return_value = AnchorType.OMG_PowerGrip
|
||||
self.values.module_system_constants.return_value = self.system_type.module_constants(self.module_type)
|
||||
self.q_z = 70.155851
|
||||
self.subject = BallastCalculator(self.values)
|
||||
|
||||
def test_summary_table(self):
|
||||
self.values.ballast_block_weight.return_value = 20
|
||||
self.values.max_system_pressure.return_value = 17
|
||||
|
||||
expected_value = {
|
||||
PanelType.Corner: {
|
||||
'anchors': [7, 5, 3, 3, 2, 2, 0, 2, 7, 4, 0],
|
||||
'ballast blocks': [9, 14, 5, 5, 3, 1, 13, 11, 11, 8, 11],
|
||||
'pressure': ['7.43', '10.31', '4.95', '4.95', '3.79', '2.64', '9.55', '8.49', '8.58', '6.76', '8.40']
|
||||
},
|
||||
PanelType.NorthSouth: {
|
||||
'anchors': [6, 5, 3, 2, 0, 1, 0, 2, 6, 4, 0],
|
||||
'ballast blocks': [14, 6, 1, 15, 19, 13, 12, 6, 12, 1, 10],
|
||||
'pressure': ['10.13', '5.44', '2.47', '10.71', '13.01', '9.46', '8.89', '5.35', '8.98', '2.47', '7.65']
|
||||
},
|
||||
PanelType.EastWest: {
|
||||
'anchors': [5, 4, 2, 2, 1, 0, 0, 2, 6, 1, 0],
|
||||
'ballast blocks': [11, 7, 2, 1, 15, 21, 12, 6, 11, 14, 6],
|
||||
'pressure': ['8.49', '6.19', '3.16', '2.58', '10.79', '14.25', '8.98', '5.52', '8.58', '10.22', '5.46']
|
||||
},
|
||||
PanelType.Middle: {
|
||||
'anchors': [5, 4, 2, 1, 0, 0, 0, 2, 6, 1, 0],
|
||||
'ballast blocks': [9, 5, 2, 15, 18, 20, 12, 5, 7, 13, 6],
|
||||
'pressure': ['7.21', '4.91', '3.02', '10.66', '12.39', '13.63', '8.93', '4.82', '6.06', '9.51', '5.32']
|
||||
},
|
||||
}
|
||||
|
||||
received_table = self.subject.summary_table(self.c_p_matrix, self.q_z)
|
||||
eq_(received_table.keys(), expected_value.keys())
|
||||
for key in expected_value.keys():
|
||||
received_table[key].pop('warnings')
|
||||
self.assertDictEqual(received_table[key], expected_value[key])
|
||||
|
||||
def test_ballast_and_trays_matrix(self):
|
||||
panels = array([
|
||||
Panel(wind_zone=5, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=6, panel_type=PanelType.NorthSouth),
|
||||
Panel(wind_zone=7, panel_type=PanelType.EastWest),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=8, panel_type=PanelType.Middle),
|
||||
Panel(wind_zone=9, panel_type=PanelType.NorthSouth),
|
||||
Panel(wind_zone=6, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=6, panel_type=PanelType.EastWest)
|
||||
])
|
||||
|
||||
self.values.ballast_block_weight.return_value = 20
|
||||
|
||||
expected_value = [
|
||||
Panel(wind_zone=5, panel_type=PanelType.Corner, ballast=1, link_tray=0, cross_tray=0, wind_anchors=2,
|
||||
pressure=2.64),
|
||||
Panel(wind_zone=6, panel_type=PanelType.NorthSouth, ballast=12, link_tray=0, cross_tray=1, wind_anchors=0,
|
||||
pressure=8.89),
|
||||
Panel(wind_zone=7, panel_type=PanelType.EastWest, ballast=6, link_tray=2, cross_tray=0, wind_anchors=2,
|
||||
pressure=5.52, warnings=[PanelWarnings.MaxPsf]),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=9, link_tray=0, cross_tray=2, wind_anchors=7,
|
||||
pressure=7.43, warnings=[PanelWarnings.MaxPsf]),
|
||||
Panel(wind_zone=8, panel_type=PanelType.Middle, ballast=7, link_tray=1, cross_tray=1, wind_anchors=6,
|
||||
pressure=6.06, warnings=[PanelWarnings.MaxPsf]),
|
||||
Panel(wind_zone=9, panel_type=PanelType.NorthSouth, ballast=1, link_tray=0, cross_tray=0, wind_anchors=4,
|
||||
pressure=2.47, warnings=[PanelWarnings.MaxPsf]),
|
||||
Panel(wind_zone=6, panel_type=PanelType.Corner, ballast=13, link_tray=0, cross_tray=0, wind_anchors=0,
|
||||
pressure=9.55),
|
||||
Panel(wind_zone=6, panel_type=PanelType.EastWest, ballast=12, link_tray=2, cross_tray=0, wind_anchors=0,
|
||||
pressure=8.98)
|
||||
]
|
||||
|
||||
assert_array_is_close(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, panels),
|
||||
expected_value, decimal=2)
|
||||
|
||||
def test_presented_link_trays(self):
|
||||
panels = [
|
||||
Panel(panel_type=PanelType.Corner, link_tray=0),
|
||||
Panel(panel_type=PanelType.NorthSouth, link_tray=0),
|
||||
Panel(panel_type=PanelType.EastWest, link_tray=2),
|
||||
Panel(panel_type=PanelType.Corner, link_tray=0),
|
||||
Panel(panel_type=PanelType.Middle, link_tray=1),
|
||||
Panel(panel_type=PanelType.NorthSouth, link_tray=0),
|
||||
Panel(panel_type=PanelType.Corner, link_tray=0),
|
||||
Panel(panel_type=PanelType.NorthSouth, link_tray=0),
|
||||
Panel(panel_type=PanelType.EastWest, link_tray=2),
|
||||
Panel(panel_type=PanelType.Middle, link_tray=1),
|
||||
Panel(panel_type=PanelType.Corner, link_tray=0),
|
||||
Panel(panel_type=PanelType.NorthSouth, link_tray=0),
|
||||
Panel(panel_type=PanelType.EastWest, link_tray=2),
|
||||
Panel(panel_type=PanelType.Middle, link_tray=1),
|
||||
]
|
||||
|
||||
expected = [
|
||||
Panel(presented_link_tray=0, panel_type=PanelType.Corner, link_tray=0),
|
||||
Panel(presented_link_tray=0, panel_type=PanelType.NorthSouth, link_tray=0),
|
||||
Panel(presented_link_tray=2, panel_type=PanelType.EastWest, link_tray=2),
|
||||
Panel(presented_link_tray=0, panel_type=PanelType.Corner, link_tray=0),
|
||||
Panel(presented_link_tray=1, panel_type=PanelType.Middle, link_tray=1),
|
||||
Panel(presented_link_tray=0, panel_type=PanelType.NorthSouth, link_tray=0),
|
||||
Panel(presented_link_tray=0, panel_type=PanelType.Corner, link_tray=0),
|
||||
Panel(presented_link_tray=0, panel_type=PanelType.NorthSouth, link_tray=0),
|
||||
Panel(presented_link_tray=2, panel_type=PanelType.EastWest, link_tray=2),
|
||||
Panel(presented_link_tray=1, panel_type=PanelType.Middle, link_tray=1),
|
||||
Panel(presented_link_tray=0, panel_type=PanelType.Corner, link_tray=0),
|
||||
Panel(presented_link_tray=0, panel_type=PanelType.NorthSouth, link_tray=0),
|
||||
Panel(presented_link_tray=2, panel_type=PanelType.EastWest, link_tray=2),
|
||||
Panel(presented_link_tray=1, panel_type=PanelType.Middle, link_tray=1)
|
||||
]
|
||||
|
||||
assert_array_equal(self.subject.show_presented_link_trays(panels), expected)
|
||||
|
||||
def test_pressure_exceeding_max_system_pressure(self):
|
||||
self.values.ballast_block_weight.return_value = 20
|
||||
self.values.max_system_pressure.return_value = 25
|
||||
|
||||
panel_data = [
|
||||
Panel(wind_zone=7, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=7, panel_type=PanelType.NorthSouth),
|
||||
Panel(wind_zone=9, panel_type=PanelType.EastWest),
|
||||
Panel(wind_zone=5, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=6, panel_type=PanelType.Middle),
|
||||
Panel(wind_zone=8, panel_type=PanelType.NorthSouth),
|
||||
Panel(wind_zone=6, panel_type=PanelType.Corner)
|
||||
]
|
||||
|
||||
expected_value = [
|
||||
Panel(wind_zone=7, panel_type=PanelType.Corner, ballast=11, link_tray=0, cross_tray=1,
|
||||
wind_anchors=2, pressure=8.49, warnings=[PanelWarnings.MaxPsf]),
|
||||
Panel(wind_zone=7, panel_type=PanelType.NorthSouth, ballast=6, link_tray=0, cross_tray=0,
|
||||
wind_anchors=2, pressure=5.35, warnings=[PanelWarnings.MaxPsf]),
|
||||
Panel(wind_zone=9, panel_type=PanelType.EastWest, ballast=29, link_tray=2, cross_tray=2,
|
||||
wind_anchors=0, pressure=18.94),
|
||||
Panel(wind_zone=5, panel_type=PanelType.Corner, ballast=1, link_tray=0, cross_tray=0,
|
||||
wind_anchors=2, pressure=2.64),
|
||||
Panel(wind_zone=6, panel_type=PanelType.Middle, ballast=12, link_tray=1, cross_tray=1,
|
||||
wind_anchors=0, pressure=8.93),
|
||||
Panel(wind_zone=8, panel_type=PanelType.NorthSouth, ballast=12, link_tray=0, cross_tray=2,
|
||||
wind_anchors=6, pressure=8.98, warnings=[PanelWarnings.MaxPsf]),
|
||||
Panel(wind_zone=6, panel_type=PanelType.Corner, ballast=13, link_tray=0, cross_tray=0,
|
||||
wind_anchors=0, pressure=9.55)
|
||||
]
|
||||
|
||||
assert_array_is_close(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, panel_data),
|
||||
expected_value, decimal=2)
|
||||
|
||||
def test_ballast_count_when_base_weight_greater_than_uplift(self):
|
||||
# Need to regenerate a c_p matrix to get to this case
|
||||
|
||||
"""
|
||||
Generated using site parameters:
|
||||
height: 30
|
||||
length: 100
|
||||
width: 100
|
||||
parapet: 0
|
||||
wind_speed: 110
|
||||
exposure_category: B
|
||||
"""
|
||||
self.c_p_matrix = array([[0.788942, 0.628471, 0.523726, 0.350229],
|
||||
[0.605171, 0.475222, 0.396018, 0.255521],
|
||||
[0.402570, 0.341277, 0.243769, 0.186968],
|
||||
[0.310157, 0.226181, 0.161558, 0.114584],
|
||||
[0.228394, 0.153519, 0.176571, 0.085682],
|
||||
[0.211896, 0.161175, 0.123981, 0.085682],
|
||||
[0.179390, 0.153519, 0.109657, 0.085682],
|
||||
[0.251345, 0.182189, 0.182189, 0.116534],
|
||||
[0.521059, 0.291372, 0.291372, 0.127381],
|
||||
[0.375420, 0.253428, 0.126714, 0.085682],
|
||||
[0.179390, 0.153519, 0.109657, 0.085682]])
|
||||
self.q_z = 18.446284
|
||||
|
||||
expected = Panel(wind_zone=10, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0,
|
||||
wind_anchors=0, pressure=1.87)
|
||||
|
||||
assert self.subject.ballast_tray_and_anchor_count(10, PanelType.Middle, 14, 1000, self.c_p_matrix,
|
||||
self.q_z).almost_equal(expected, decimal=2)
|
||||
|
||||
def test_individual_ballast_block_uplift_greater_than_base_weight(self):
|
||||
expected = Panel(wind_zone=6, panel_type=PanelType.Middle, ballast=16, link_tray=1, cross_tray=1,
|
||||
wind_anchors=0, pressure=8.47)
|
||||
assert self.subject.ballast_tray_and_anchor_count(6, PanelType.Middle, 14, 1000, self.c_p_matrix,
|
||||
self.q_z).almost_equal(expected, decimal=2)
|
||||
|
||||
expected = Panel(wind_zone=6, panel_type=PanelType.Middle, ballast=12, link_tray=1, cross_tray=1,
|
||||
wind_anchors=0, pressure=8.93)
|
||||
assert self.subject.ballast_tray_and_anchor_count(6, PanelType.Middle, 20, 1000, self.c_p_matrix,
|
||||
self.q_z).almost_equal(expected, decimal=2)
|
||||
|
||||
def test_ballast_blocks_exceeding_tray_capacity(self):
|
||||
expected = Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=9, link_tray=0, cross_tray=2,
|
||||
wind_anchors=7, pressure=7.43, warnings=[PanelWarnings.MaxPsf])
|
||||
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Corner, 20, 1000, self.c_p_matrix,
|
||||
self.q_z).almost_equal(expected, decimal=2)
|
||||
|
||||
expected = Panel(wind_zone=8, panel_type=PanelType.Middle, ballast=7, link_tray=1, cross_tray=1,
|
||||
wind_anchors=6, pressure=6.06, warnings=[PanelWarnings.MaxPsf])
|
||||
assert self.subject.ballast_tray_and_anchor_count(8, PanelType.Middle, 20, 1000, self.c_p_matrix,
|
||||
self.q_z).almost_equal(expected, decimal=2)
|
||||
|
||||
def test_ballast_blocks_when_panel_exceeds_max_system_pressure(self):
|
||||
expected = Panel(wind_zone=5, panel_type=PanelType.Middle, ballast=7, link_tray=1, cross_tray=0,
|
||||
wind_anchors=1, pressure=4.76)
|
||||
assert self.subject.ballast_tray_and_anchor_count(5, PanelType.Middle, 14, 10, self.c_p_matrix,
|
||||
self.q_z).almost_equal(expected, decimal=2)
|
||||
|
||||
expected = Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=13, link_tray=0, cross_tray=2,
|
||||
wind_anchors=7, pressure=7.49, warnings=[PanelWarnings.MaxPsf])
|
||||
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Corner, 14, 10, self.c_p_matrix,
|
||||
self.q_z).almost_equal(expected, decimal=2)
|
||||
|
||||
def test_when_max_system_pressure_is_lower_than_base_weight_pressure(self):
|
||||
max_system_pressure = 0
|
||||
|
||||
expected = Panel(wind_zone=5, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0,
|
||||
wind_anchors=2, pressure=1.87)
|
||||
assert self.subject.ballast_tray_and_anchor_count(5, PanelType.Middle, 12, max_system_pressure,
|
||||
self.c_p_matrix, self.q_z).almost_equal(
|
||||
expected,
|
||||
decimal=2
|
||||
)
|
||||
|
||||
def test_uplift(self):
|
||||
assert_almost_equal(self.subject.uplift(1.506920, self.q_z), 2462.20, 2)
|
||||
|
||||
def test_calculate_single_unit_pressure_on_roof(self):
|
||||
assert_almost_equal(self.subject.calculate_pressure_on_roof(90, 20, 59.1), 53.48, 2)
|
||||
assert_almost_equal(self.subject.calculate_pressure_on_roof(15, 14, 54.5), 7.61, 2)
|
||||
@@ -0,0 +1,231 @@
|
||||
import unittest
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from nose.tools import assert_almost_equal, eq_
|
||||
from numpy import array
|
||||
from numpy.testing import assert_array_equal
|
||||
|
||||
from helix.calculators.ballast_calculator import BallastCalculator
|
||||
from helix.constants.anchor_type import AnchorType
|
||||
from helix.constants.module_type import ModuleType
|
||||
from helix.constants.panel_type import PanelType
|
||||
from helix.constants.system_type import SystemType
|
||||
from helix.models.panel import Panel, PanelWarnings
|
||||
from test.test_helpers import assert_array_is_close
|
||||
|
||||
|
||||
class BallastCalculatorWhenSingleTiltAnd96CellTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.values = MagicMock()
|
||||
"""
|
||||
Generated using site parameters:
|
||||
height: 100
|
||||
length: 1000
|
||||
width: 1500
|
||||
parapet: 0
|
||||
wind_speed: 150
|
||||
exposure_category: D
|
||||
"""
|
||||
|
||||
self.c_p_matrix = array([[1.506920, 1.347220, 1.122684, 0.948795],
|
||||
[1.186590, 1.057265, 0.881054, 0.740239],
|
||||
[0.676809, 0.615810, 0.439865, 0.382935],
|
||||
[0.685883, 0.602310, 0.430222, 0.352224],
|
||||
[0.460258, 0.272456, 0.408684, 0.227532],
|
||||
[0.438829, 0.388352, 0.298733, 0.247999],
|
||||
[0.206406, 0.186191, 0.186191, 0.159779],
|
||||
[0.560763, 0.491939, 0.491939, 0.402013],
|
||||
[1.548721, 1.320138, 1.320138, 1.021469],
|
||||
[0.921232, 0.799827, 0.399914, 0.320599],
|
||||
[0.168333, 0.142587, 0.101848, 0.078692]])
|
||||
self.system_type = SystemType.singleTilt
|
||||
self.module_type = ModuleType.Cell96
|
||||
self.values.max_system_pressure.return_value = 1000
|
||||
self.values.system_type.return_value = self.system_type
|
||||
self.values.anchor_type.return_value = AnchorType.OMG_PowerGrip
|
||||
self.values.module_system_constants.return_value = self.system_type.module_constants(self.module_type)
|
||||
self.q_z = 70.155851
|
||||
self.subject = BallastCalculator(self.values)
|
||||
|
||||
def test_summary_table(self):
|
||||
self.values.ballast_block_weight.return_value = 20
|
||||
self.values.max_system_pressure.return_value = 17
|
||||
|
||||
expected_value = {
|
||||
PanelType.Corner: {
|
||||
'anchors': [5, 4, 2, 2, 1, 1, 0, 2, 6, 3, 0],
|
||||
'ballast blocks': [14, 10, 9, 9, 11, 10, 10, 2, 2, 9, 8],
|
||||
'pressure': ['12.93', '9.79', '9.03', '9.03', '10.56', '9.70', '9.70', '3.60', '3.69', '9.03', '8.18']
|
||||
},
|
||||
PanelType.NorthSouth: {
|
||||
'anchors': [5, 4, 2, 2, 0, 1, 0, 1, 5, 3, 0],
|
||||
'ballast blocks': [5, 2, 5, 5, 15, 7, 9, 13, 3, 2, 7],
|
||||
'pressure': ['5.79', '3.50', '5.70', '5.70', '13.41', '7.23', '8.84', '11.89', '4.26', '3.41', '7.23']
|
||||
},
|
||||
PanelType.EastWest: {
|
||||
'anchors': [4, 3, 1, 1, 1, 0, 0, 1, 5, 1, 0],
|
||||
'ballast blocks': [6, 6, 10, 9, 8, 16, 9, 13, 3, 7, 4],
|
||||
'pressure': ['6.79', '6.70', '9.75', '8.99', '8.23', '14.42', '8.99', '12.13', '4.41', '7.46', '5.09']
|
||||
},
|
||||
PanelType.Middle: {
|
||||
'anchors': [3, 2, 1, 0, 0, 0, 0, 1, 3, 0, 0],
|
||||
'ballast blocks': [11, 13, 6, 19, 12, 13, 8, 7, 15, 18, 3],
|
||||
'pressure': ['10.42', '11.95', '6.52', '16.61', '11.19', '11.95', '8.05', '7.29', '13.56', '15.76',
|
||||
'4.15']
|
||||
},
|
||||
}
|
||||
|
||||
received_table = self.subject.summary_table(self.c_p_matrix, self.q_z)
|
||||
eq_(received_table.keys(), expected_value.keys())
|
||||
for key in expected_value.keys():
|
||||
received_table[key].pop('warnings')
|
||||
self.assertDictEqual(received_table[key], expected_value[key])
|
||||
|
||||
def test_ballast_and_trays_matrix(self):
|
||||
panels = [
|
||||
Panel(wind_zone=5, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=6, panel_type=PanelType.NorthSouth),
|
||||
Panel(wind_zone=7, panel_type=PanelType.EastWest),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=8, panel_type=PanelType.Middle),
|
||||
Panel(wind_zone=9, panel_type=PanelType.NorthSouth),
|
||||
Panel(wind_zone=6, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=6, panel_type=PanelType.EastWest)
|
||||
]
|
||||
|
||||
self.values.ballast_block_weight.return_value = 20
|
||||
|
||||
expected_value = [
|
||||
Panel(wind_zone=5, panel_type=PanelType.Corner, ballast=25, link_tray=0, cross_tray=2, wind_anchors=0, pressure=21.32),
|
||||
Panel(wind_zone=6, panel_type=PanelType.NorthSouth, ballast=9, link_tray=0, cross_tray=1, wind_anchors=0, pressure=8.84),
|
||||
Panel(wind_zone=7, panel_type=PanelType.EastWest, ballast=28, link_tray=2, cross_tray=2, wind_anchors=0, pressure=23.65),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=14, link_tray=0, cross_tray=2, wind_anchors=5, pressure=12.93, warnings=[PanelWarnings.MaxPsf]),
|
||||
Panel(wind_zone=8, panel_type=PanelType.Middle, ballast=15, link_tray=1, cross_tray=2, wind_anchors=3, pressure=13.56, warnings=[PanelWarnings.MaxPsf]),
|
||||
Panel(wind_zone=9, panel_type=PanelType.NorthSouth, ballast=2, link_tray=0, cross_tray=0, wind_anchors=3, pressure=3.41, warnings=[PanelWarnings.MaxPsf]),
|
||||
Panel(wind_zone=6, panel_type=PanelType.Corner, ballast=10, link_tray=0, cross_tray=0, wind_anchors=0, pressure=9.70),
|
||||
Panel(wind_zone=6, panel_type=PanelType.EastWest, ballast=9, link_tray=2, cross_tray=0, wind_anchors=0, pressure=8.99)
|
||||
]
|
||||
|
||||
assert_array_is_close(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, panels), expected_value, decimal=2)
|
||||
|
||||
def test_presented_link_trays(self):
|
||||
panels = [
|
||||
Panel(panel_type=PanelType.Corner, link_tray=0),
|
||||
Panel(panel_type=PanelType.NorthSouth, link_tray=0),
|
||||
Panel(panel_type=PanelType.EastWest, link_tray=2),
|
||||
Panel(panel_type=PanelType.Corner, link_tray=0),
|
||||
Panel(panel_type=PanelType.Middle, link_tray=1),
|
||||
Panel(panel_type=PanelType.NorthSouth, link_tray=0),
|
||||
Panel(panel_type=PanelType.Corner, link_tray=0),
|
||||
Panel(panel_type=PanelType.NorthSouth, link_tray=0),
|
||||
Panel(panel_type=PanelType.EastWest, link_tray=2),
|
||||
Panel(panel_type=PanelType.Middle, link_tray=1),
|
||||
Panel(panel_type=PanelType.Corner, link_tray=0),
|
||||
Panel(panel_type=PanelType.NorthSouth, link_tray=0),
|
||||
Panel(panel_type=PanelType.EastWest, link_tray=2),
|
||||
Panel(panel_type=PanelType.Middle, link_tray=1),
|
||||
]
|
||||
self.values.ballast_block_weight.return_value = 20
|
||||
|
||||
expected_value = [
|
||||
Panel(presented_link_tray=0, panel_type=PanelType.Corner, link_tray=0),
|
||||
Panel(presented_link_tray=0, panel_type=PanelType.NorthSouth, link_tray=0),
|
||||
Panel(presented_link_tray=2, panel_type=PanelType.EastWest, link_tray=2),
|
||||
Panel(presented_link_tray=0, panel_type=PanelType.Corner, link_tray=0),
|
||||
Panel(presented_link_tray=1, panel_type=PanelType.Middle, link_tray=1),
|
||||
Panel(presented_link_tray=0, panel_type=PanelType.NorthSouth, link_tray=0),
|
||||
Panel(presented_link_tray=0, panel_type=PanelType.Corner, link_tray=0),
|
||||
Panel(presented_link_tray=0, panel_type=PanelType.NorthSouth, link_tray=0),
|
||||
Panel(presented_link_tray=2, panel_type=PanelType.EastWest, link_tray=2),
|
||||
Panel(presented_link_tray=1, panel_type=PanelType.Middle, link_tray=1),
|
||||
Panel(presented_link_tray=0, panel_type=PanelType.Corner, link_tray=0),
|
||||
Panel(presented_link_tray=0, panel_type=PanelType.NorthSouth, link_tray=0),
|
||||
Panel(presented_link_tray=2, panel_type=PanelType.EastWest, link_tray=2),
|
||||
Panel(presented_link_tray=1, panel_type=PanelType.Middle, link_tray=1)
|
||||
]
|
||||
|
||||
assert_array_equal(self.subject.show_presented_link_trays(panels), expected_value)
|
||||
|
||||
def test_pressure_exceeding_max_system_pressure(self):
|
||||
self.values.ballast_block_weight.return_value = 20
|
||||
self.values.max_system_pressure.return_value = 25
|
||||
panels = [
|
||||
Panel(wind_zone=7, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=7, panel_type=PanelType.NorthSouth),
|
||||
Panel(wind_zone=9, panel_type=PanelType.EastWest),
|
||||
Panel(wind_zone=5, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=6, panel_type=PanelType.Middle),
|
||||
Panel(wind_zone=8, panel_type=PanelType.NorthSouth),
|
||||
Panel(wind_zone=6, panel_type=PanelType.Corner)
|
||||
]
|
||||
|
||||
expected_value = array([
|
||||
Panel(wind_zone=7, panel_type=PanelType.Corner, ballast=2, link_tray=0, cross_tray=0, wind_anchors=2, pressure=3.60),
|
||||
Panel(wind_zone=7, panel_type=PanelType.NorthSouth, ballast=13, link_tray=0, cross_tray=1, wind_anchors=1, pressure=11.89),
|
||||
Panel(wind_zone=9, panel_type=PanelType.EastWest, ballast=22, link_tray=2, cross_tray=1, wind_anchors=0, pressure=18.99),
|
||||
Panel(wind_zone=5, panel_type=PanelType.Corner, ballast=25, link_tray=0, cross_tray=2, wind_anchors=0, pressure=21.32),
|
||||
Panel(wind_zone=6, panel_type=PanelType.Middle, ballast=8, link_tray=1, cross_tray=0, wind_anchors=0, pressure=8.05),
|
||||
Panel(wind_zone=8, panel_type=PanelType.NorthSouth, ballast=3, link_tray=0, cross_tray=1, wind_anchors=5, pressure=4.26, warnings=[PanelWarnings.MaxPsf]),
|
||||
Panel(wind_zone=6, panel_type=PanelType.Corner, ballast=10, link_tray=0, cross_tray=0, wind_anchors=0, pressure=9.70),
|
||||
])
|
||||
|
||||
assert_array_is_close(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, panels), expected_value, decimal=2)
|
||||
|
||||
def test_ballast_count_when_base_weight_greater_than_uplift(self):
|
||||
assert self.subject.ballast_tray_and_anchor_count(10, PanelType.Middle, 14, 1000, self.c_p_matrix,
|
||||
30.155851).almost_equal(
|
||||
Panel(wind_zone=10, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0,
|
||||
wind_anchors=0, pressure=1.86),
|
||||
decimal=2)
|
||||
|
||||
def test_individual_ballast_block_uplift_greater_than_base_weight(self):
|
||||
assert self.subject.ballast_tray_and_anchor_count(6, PanelType.Middle, 14, 1000, self.c_p_matrix,
|
||||
self.q_z).almost_equal(
|
||||
Panel(wind_zone=6, panel_type=PanelType.Middle, ballast=11, link_tray=1, cross_tray=1,
|
||||
wind_anchors=0, pressure=7.91),
|
||||
decimal=2)
|
||||
assert self.subject.ballast_tray_and_anchor_count(6, PanelType.Middle, 20, 1000, self.c_p_matrix,
|
||||
self.q_z).almost_equal(
|
||||
Panel(wind_zone=6, panel_type=PanelType.Middle, ballast=8, link_tray=1, cross_tray=0,
|
||||
wind_anchors=0, pressure=8.05),
|
||||
decimal=2)
|
||||
|
||||
def test_ballast_blocks_exceeding_tray_capacity(self):
|
||||
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Corner, 20, 1000, self.c_p_matrix,
|
||||
self.q_z).almost_equal(
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=14, link_tray=0, cross_tray=2,
|
||||
wind_anchors=5, pressure=12.93, warnings=[PanelWarnings.MaxPsf]),
|
||||
decimal=2)
|
||||
assert self.subject.ballast_tray_and_anchor_count(8, PanelType.Middle, 20, 1000, self.c_p_matrix,
|
||||
self.q_z).almost_equal(
|
||||
Panel(wind_zone=8, panel_type=PanelType.Middle, ballast=15, link_tray=1, cross_tray=2,
|
||||
wind_anchors=3, pressure=13.56, warnings=[PanelWarnings.MaxPsf]),
|
||||
decimal=2)
|
||||
|
||||
def test_ballast_blocks_when_panel_exceeds_max_system_pressure(self):
|
||||
assert self.subject.ballast_tray_and_anchor_count(5, PanelType.Middle, 14, 10, self.c_p_matrix,
|
||||
self.q_z).almost_equal(
|
||||
Panel(wind_zone=5, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0,
|
||||
wind_anchors=1, pressure=1.86),
|
||||
decimal=2)
|
||||
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Corner, 14, 10, self.c_p_matrix,
|
||||
self.q_z).almost_equal(
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=0, link_tray=0, cross_tray=0,
|
||||
wind_anchors=6, pressure=2.08, warnings=[PanelWarnings.MaxPsf]),
|
||||
decimal=2)
|
||||
|
||||
def test_when_max_system_pressure_is_lower_than_base_weight_pressure(self):
|
||||
max_system_pressure = 0
|
||||
|
||||
assert self.subject.ballast_tray_and_anchor_count(5, PanelType.Middle, 12, max_system_pressure, self.c_p_matrix,
|
||||
self.q_z).almost_equal(
|
||||
Panel(wind_zone=5, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0,
|
||||
wind_anchors=1, pressure=1.86),
|
||||
decimal=2)
|
||||
|
||||
def test_uplift(self):
|
||||
assert_almost_equal(self.subject.uplift(1.506920, self.q_z), 1857.49, 1)
|
||||
|
||||
def test_calculate_single_unit_pressure_on_roof(self):
|
||||
assert_almost_equal(self.subject.calculate_pressure_on_roof(90, 20, 59.1), 70.89, 2)
|
||||
assert_almost_equal(self.subject.calculate_pressure_on_roof(15, 14, 54.5), 10.09, 2)
|
||||
@@ -0,0 +1,276 @@
|
||||
import unittest
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from nose.tools import assert_almost_equal, eq_
|
||||
from numpy import array
|
||||
from numpy.testing import assert_array_equal
|
||||
|
||||
from helix.calculators.ballast_calculator import BallastCalculator
|
||||
from helix.constants.anchor_type import AnchorType
|
||||
from helix.constants.module_type import ModuleType
|
||||
from helix.constants.panel_type import PanelType
|
||||
from helix.constants.system_type import SystemType
|
||||
from helix.models.panel import Panel, PanelWarnings
|
||||
from test.test_helpers import assert_array_is_close
|
||||
|
||||
|
||||
class BallastCalculatorWhenSingleTiltAndPSeriesTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.values = MagicMock()
|
||||
"""
|
||||
Generated using site parameters:
|
||||
height: 100
|
||||
length: 1000
|
||||
width: 1500
|
||||
parapet: 0
|
||||
wind_speed: 150
|
||||
exposure_category: D
|
||||
"""
|
||||
|
||||
self.c_p_matrix = array([[1.475479, 1.345176, 1.120980, 1.088447],
|
||||
[1.161129, 1.055610, 0.879675, 0.853329],
|
||||
[0.664800, 0.615030, 0.439307, 0.428656],
|
||||
[0.669430, 0.601241, 0.429458, 0.414865],
|
||||
[0.450104, 0.272016, 0.408024, 0.263611],
|
||||
[0.428892, 0.387706, 0.298236, 0.288744],
|
||||
[0.202426, 0.185933, 0.185933, 0.180991],
|
||||
[0.547213, 0.491058, 0.491058, 0.474234],
|
||||
[1.503719, 1.317213, 1.317213, 1.261333],
|
||||
[0.897331, 0.798273, 0.399137, 0.384297],
|
||||
[0.172217, 0.151210, 0.108007, 0.103511]])
|
||||
self.system_type = SystemType.singleTilt
|
||||
self.module_type = ModuleType.PSeries
|
||||
self.values.max_system_pressure.return_value = 1000
|
||||
self.values.system_type.return_value = self.system_type
|
||||
self.values.anchor_type.return_value = AnchorType.OMG_PowerGrip
|
||||
self.values.module_system_constants.return_value = self.system_type.module_constants(self.module_type)
|
||||
self.q_z = 70.155851
|
||||
self.subject = BallastCalculator(self.values)
|
||||
|
||||
def test_summary_table(self):
|
||||
self.values.ballast_block_weight.return_value = 20
|
||||
self.values.max_system_pressure.return_value = 17
|
||||
|
||||
expected_value = {
|
||||
PanelType.Corner: {
|
||||
'anchors': [7, 5, 3, 3, 2, 1, 0, 2, 7, 4, 0],
|
||||
'ballast blocks': [5, 11, 3, 4, 2, 15, 13, 9, 7, 6, 11],
|
||||
'pressure': ['5.13', '8.75', '3.83', '4.43', '3.22', '11.16', '9.86', '7.45', '6.33', '5.73', '8.65']
|
||||
},
|
||||
PanelType.NorthSouth: {
|
||||
'anchors': [6, 5, 2, 2, 0, 1, 0, 2, 6, 3, 0],
|
||||
'ballast blocks': [10, 3, 15, 14, 18, 12, 12, 5, 8, 14, 9],
|
||||
'pressure': ['8.06', '3.74', '11.07', '10.37', '12.88', '9.17', '9.17', '4.85', '6.85', '10.47', '7.26']
|
||||
},
|
||||
PanelType.EastWest: {
|
||||
'anchors': [5, 4, 2, 1, 1, 0, 0, 2, 6, 1, 0],
|
||||
'ballast blocks': [8, 5, 1, 15, 14, 20, 12, 5, 8, 13, 6],
|
||||
'pressure': ['6.94', '5.04', '2.56', '11.16', '10.56', '14.18', '9.26', '5.04', '6.94', '9.96', '5.57']
|
||||
},
|
||||
PanelType.Middle: {
|
||||
'anchors': [5, 4, 1, 1, 0, 0, 0, 2, 6, 1, 0],
|
||||
'ballast blocks': [6, 3, 15, 14, 18, 20, 11, 4, 4, 12, 6],
|
||||
'pressure': ['5.60', '3.69', '11.02', '10.42', '12.83', '14.13', '8.51', '4.29', '4.39', '9.21', '5.43']
|
||||
},
|
||||
}
|
||||
|
||||
received_table = self.subject.summary_table(self.c_p_matrix, self.q_z)
|
||||
|
||||
eq_(received_table.keys(), expected_value.keys())
|
||||
for key in expected_value.keys():
|
||||
received_table[key].pop('warnings')
|
||||
self.assertDictEqual(received_table[key], expected_value[key])
|
||||
|
||||
def test_ballast_and_trays_matrix(self):
|
||||
panels = array([
|
||||
Panel(wind_zone=5, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=6, panel_type=PanelType.NorthSouth),
|
||||
Panel(wind_zone=7, panel_type=PanelType.EastWest),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=8, panel_type=PanelType.Middle),
|
||||
Panel(wind_zone=9, panel_type=PanelType.NorthSouth),
|
||||
Panel(wind_zone=6, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=6, panel_type=PanelType.EastWest)
|
||||
])
|
||||
|
||||
self.values.ballast_block_weight.return_value = 20
|
||||
|
||||
expected_value = [
|
||||
Panel(wind_zone=5, panel_type=PanelType.Corner, ballast=15, link_tray=0, cross_tray=1, wind_anchors=1,
|
||||
pressure=11.16),
|
||||
Panel(wind_zone=6, panel_type=PanelType.NorthSouth, ballast=12, link_tray=0, cross_tray=1, wind_anchors=0,
|
||||
pressure=9.17),
|
||||
Panel(wind_zone=7, panel_type=PanelType.EastWest, ballast=5, link_tray=2, cross_tray=0, wind_anchors=2,
|
||||
pressure=5.04, warnings=[PanelWarnings.MaxPsf]),
|
||||
Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=5, link_tray=0, cross_tray=1, wind_anchors=7,
|
||||
pressure=5.13, warnings=[PanelWarnings.MaxPsf]),
|
||||
Panel(wind_zone=8, panel_type=PanelType.Middle, ballast=4, link_tray=1, cross_tray=1, wind_anchors=6,
|
||||
pressure=4.39, warnings=[PanelWarnings.MaxPsf]),
|
||||
Panel(wind_zone=9, panel_type=PanelType.NorthSouth, ballast=14, link_tray=0, cross_tray=2, wind_anchors=3,
|
||||
pressure=10.47, warnings=[PanelWarnings.MaxPsf]),
|
||||
Panel(wind_zone=6, panel_type=PanelType.Corner, ballast=13, link_tray=0, cross_tray=0, wind_anchors=0,
|
||||
pressure=9.86),
|
||||
Panel(wind_zone=6, panel_type=PanelType.EastWest, ballast=12, link_tray=2, cross_tray=0, wind_anchors=0,
|
||||
pressure=9.26)
|
||||
]
|
||||
|
||||
assert_array_is_close(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, panels),
|
||||
expected_value, decimal=2)
|
||||
|
||||
def test_presented_link_trays(self):
|
||||
panels = [
|
||||
Panel(panel_type=PanelType.Corner, link_tray=0),
|
||||
Panel(panel_type=PanelType.NorthSouth, link_tray=0),
|
||||
Panel(panel_type=PanelType.EastWest, link_tray=2),
|
||||
Panel(panel_type=PanelType.Corner, link_tray=0),
|
||||
Panel(panel_type=PanelType.Middle, link_tray=1),
|
||||
Panel(panel_type=PanelType.NorthSouth, link_tray=0),
|
||||
Panel(panel_type=PanelType.Corner, link_tray=0),
|
||||
Panel(panel_type=PanelType.NorthSouth, link_tray=0),
|
||||
Panel(panel_type=PanelType.EastWest, link_tray=2),
|
||||
Panel(panel_type=PanelType.Middle, link_tray=1),
|
||||
Panel(panel_type=PanelType.Corner, link_tray=0),
|
||||
Panel(panel_type=PanelType.NorthSouth, link_tray=0),
|
||||
Panel(panel_type=PanelType.EastWest, link_tray=2),
|
||||
Panel(panel_type=PanelType.Middle, link_tray=1),
|
||||
]
|
||||
|
||||
expected = [
|
||||
Panel(presented_link_tray=0, panel_type=PanelType.Corner, link_tray=0),
|
||||
Panel(presented_link_tray=0, panel_type=PanelType.NorthSouth, link_tray=0),
|
||||
Panel(presented_link_tray=2, panel_type=PanelType.EastWest, link_tray=2),
|
||||
Panel(presented_link_tray=0, panel_type=PanelType.Corner, link_tray=0),
|
||||
Panel(presented_link_tray=1, panel_type=PanelType.Middle, link_tray=1),
|
||||
Panel(presented_link_tray=0, panel_type=PanelType.NorthSouth, link_tray=0),
|
||||
Panel(presented_link_tray=0, panel_type=PanelType.Corner, link_tray=0),
|
||||
Panel(presented_link_tray=0, panel_type=PanelType.NorthSouth, link_tray=0),
|
||||
Panel(presented_link_tray=2, panel_type=PanelType.EastWest, link_tray=2),
|
||||
Panel(presented_link_tray=1, panel_type=PanelType.Middle, link_tray=1),
|
||||
Panel(presented_link_tray=0, panel_type=PanelType.Corner, link_tray=0),
|
||||
Panel(presented_link_tray=0, panel_type=PanelType.NorthSouth, link_tray=0),
|
||||
Panel(presented_link_tray=2, panel_type=PanelType.EastWest, link_tray=2),
|
||||
Panel(presented_link_tray=1, panel_type=PanelType.Middle, link_tray=1)
|
||||
]
|
||||
|
||||
assert_array_equal(self.subject.show_presented_link_trays(panels), expected)
|
||||
|
||||
def test_pressure_exceeding_max_system_pressure(self):
|
||||
self.values.ballast_block_weight.return_value = 20
|
||||
self.values.max_system_pressure.return_value = 25
|
||||
|
||||
panel_data = [
|
||||
Panel(wind_zone=7, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=7, panel_type=PanelType.NorthSouth),
|
||||
Panel(wind_zone=9, panel_type=PanelType.EastWest),
|
||||
Panel(wind_zone=5, panel_type=PanelType.Corner),
|
||||
Panel(wind_zone=6, panel_type=PanelType.Middle),
|
||||
Panel(wind_zone=8, panel_type=PanelType.NorthSouth),
|
||||
Panel(wind_zone=6, panel_type=PanelType.Corner)
|
||||
]
|
||||
|
||||
expected_value = [
|
||||
Panel(wind_zone=7, panel_type=PanelType.Corner, ballast=9, link_tray=0, cross_tray=0,
|
||||
wind_anchors=2, pressure=7.44, warnings=[PanelWarnings.MaxPsf]),
|
||||
Panel(wind_zone=7, panel_type=PanelType.NorthSouth, ballast=5, link_tray=0, cross_tray=0,
|
||||
wind_anchors=2, pressure=4.85, warnings=[PanelWarnings.MaxPsf]),
|
||||
Panel(wind_zone=9, panel_type=PanelType.EastWest, ballast=28, link_tray=2, cross_tray=2,
|
||||
wind_anchors=0, pressure=19.10),
|
||||
Panel(wind_zone=5, panel_type=PanelType.Corner, ballast=15, link_tray=0, cross_tray=1,
|
||||
wind_anchors=1, pressure=11.16),
|
||||
Panel(wind_zone=6, panel_type=PanelType.Middle, ballast=11, link_tray=1, cross_tray=0,
|
||||
wind_anchors=0, pressure=8.51),
|
||||
Panel(wind_zone=8, panel_type=PanelType.NorthSouth, ballast=8, link_tray=0, cross_tray=2,
|
||||
wind_anchors=6, pressure=6.85, warnings=[PanelWarnings.MaxPsf]),
|
||||
Panel(wind_zone=6, panel_type=PanelType.Corner, ballast=13, link_tray=0, cross_tray=0,
|
||||
wind_anchors=0, pressure=9.86)
|
||||
]
|
||||
|
||||
assert_array_is_close(self.subject.ballast_and_trays_matrix(self.c_p_matrix, self.q_z, panel_data),
|
||||
expected_value, decimal=2)
|
||||
|
||||
def test_ballast_count_when_base_weight_greater_than_uplift(self):
|
||||
# Need to regenerate a c_p matrix to get to this case
|
||||
|
||||
"""
|
||||
Generated using site parameters:
|
||||
height: 30
|
||||
length: 100
|
||||
width: 100
|
||||
parapet: 0
|
||||
wind_speed: 110
|
||||
exposure_category: B
|
||||
"""
|
||||
self.c_p_matrix = array([[0.831094, 0.670280, 0.558567, 0.384751],
|
||||
[0.639306, 0.509079, 0.424233, 0.283477],
|
||||
[0.418671, 0.357246, 0.255176, 0.198270],
|
||||
[0.332216, 0.248060, 0.177186, 0.122119],
|
||||
[0.242006, 0.158462, 0.190073, 0.089168],
|
||||
[0.225219, 0.174390, 0.134146, 0.089168],
|
||||
[0.184388, 0.158462, 0.113187, 0.089168],
|
||||
[0.269511, 0.200207, 0.200207, 0.127913],
|
||||
[0.581392, 0.351215, 0.351215, 0.150139],
|
||||
[0.407464, 0.285212, 0.142606, 0.089168],
|
||||
[0.184388, 0.158462, 0.113187, 0.089168]])
|
||||
self.q_z = 18.446284
|
||||
|
||||
expected = Panel(wind_zone=10, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0,
|
||||
wind_anchors=0, pressure=1.81)
|
||||
|
||||
assert self.subject.ballast_tray_and_anchor_count(10, PanelType.Middle, 14, 1000, self.c_p_matrix,
|
||||
self.q_z).almost_equal(expected, decimal=2)
|
||||
|
||||
def test_ballast_and_tray_count_iterates_on_link_and_cross_trays_changing_weight_and_ballast_requirements(self):
|
||||
panel = self.subject.ballast_tray_and_anchor_count(3, PanelType.NorthSouth, 20, 17, self.c_p_matrix, self.q_z)
|
||||
assert_almost_equal(panel.pressure, 10.37, 2)
|
||||
|
||||
def test_individual_ballast_block_uplift_greater_than_base_weight(self):
|
||||
expected = Panel(wind_zone=6, panel_type=PanelType.Middle, ballast=16, link_tray=1, cross_tray=1,
|
||||
wind_anchors=0, pressure=8.73)
|
||||
assert self.subject.ballast_tray_and_anchor_count(6, PanelType.Middle, 14, 1000, self.c_p_matrix,
|
||||
self.q_z).almost_equal(expected, decimal=2)
|
||||
|
||||
expected = Panel(wind_zone=6, panel_type=PanelType.Middle, ballast=11, link_tray=1, cross_tray=0,
|
||||
wind_anchors=0, pressure=8.51)
|
||||
assert self.subject.ballast_tray_and_anchor_count(6, PanelType.Middle, 20, 1000, self.c_p_matrix,
|
||||
self.q_z).almost_equal(expected, decimal=2)
|
||||
|
||||
def test_ballast_blocks_exceeding_tray_capacity(self):
|
||||
expected = Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=5, link_tray=0, cross_tray=1,
|
||||
wind_anchors=7, pressure=5.13, warnings=[PanelWarnings.MaxPsf])
|
||||
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Corner, 20, 1000, self.c_p_matrix,
|
||||
self.q_z).almost_equal(expected, decimal=2)
|
||||
|
||||
expected = Panel(wind_zone=8, panel_type=PanelType.Middle, ballast=4, link_tray=1, cross_tray=1,
|
||||
wind_anchors=6, pressure=4.39, warnings=[PanelWarnings.MaxPsf])
|
||||
assert self.subject.ballast_tray_and_anchor_count(8, PanelType.Middle, 20, 1000, self.c_p_matrix,
|
||||
self.q_z).almost_equal(expected, decimal=2)
|
||||
|
||||
def test_ballast_blocks_when_panel_exceeds_max_system_pressure(self):
|
||||
expected = Panel(wind_zone=5, panel_type=PanelType.Middle, ballast=6, link_tray=1, cross_tray=0,
|
||||
wind_anchors=1, pressure=4.41)
|
||||
|
||||
assert self.subject.ballast_tray_and_anchor_count(5, PanelType.Middle, 14, 10, self.c_p_matrix,
|
||||
self.q_z).almost_equal(expected, decimal=2)
|
||||
|
||||
expected = Panel(wind_zone=0, panel_type=PanelType.Corner, ballast=7, link_tray=0, cross_tray=1,
|
||||
wind_anchors=7, pressure=5.07, warnings=[PanelWarnings.MaxPsf])
|
||||
assert self.subject.ballast_tray_and_anchor_count(0, PanelType.Corner, 14, 10, self.c_p_matrix,
|
||||
self.q_z).almost_equal(expected, decimal=2)
|
||||
|
||||
def test_when_max_system_pressure_is_lower_than_base_weight_pressure(self):
|
||||
max_system_pressure = 0
|
||||
|
||||
expected = Panel(wind_zone=5, panel_type=PanelType.Middle, ballast=0, link_tray=0, cross_tray=0,
|
||||
wind_anchors=2, pressure=1.81)
|
||||
assert self.subject.ballast_tray_and_anchor_count(5, PanelType.Middle, 12, max_system_pressure,
|
||||
self.c_p_matrix, self.q_z).almost_equal(
|
||||
expected,
|
||||
decimal=2
|
||||
)
|
||||
|
||||
def test_uplift(self):
|
||||
assert_almost_equal(self.subject.uplift(1.506920, self.q_z), 2349.08, 2)
|
||||
|
||||
def test_calculate_single_unit_pressure_on_roof(self): # Do manually, don't need excel
|
||||
assert_almost_equal(self.subject.calculate_pressure_on_roof(90, 20, 59.1), 56.06, 2)
|
||||
assert_almost_equal(self.subject.calculate_pressure_on_roof(15, 14, 54.5), 7.98, 2)
|
||||
@@ -0,0 +1,60 @@
|
||||
import unittest
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from nose.tools import assert_almost_equal, eq_
|
||||
from numpy import array
|
||||
from numpy.testing import assert_array_equal
|
||||
|
||||
from helix.calculators.ballast_calculator import BallastCalculator
|
||||
from helix.constants.anchor_type import AnchorType
|
||||
from helix.constants.module_type import ModuleType
|
||||
from helix.constants.panel_type import PanelType
|
||||
from helix.constants.system_type import SystemType
|
||||
from helix.models.panel import Panel, PanelWarnings
|
||||
from test.test_helpers import assert_array_is_close
|
||||
|
||||
|
||||
class BallastCalculatorUpliftWarningsTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.values = MagicMock()
|
||||
"""
|
||||
Generated using site parameters:
|
||||
height: 100
|
||||
length: 1000
|
||||
width: 1500
|
||||
parapet: 0
|
||||
wind_speed: 150
|
||||
exposure_category: D
|
||||
"""
|
||||
|
||||
self.c_p_matrix = array([[1.506920, 1.347220, 1.122684, 0.948795],
|
||||
[1.186590, 1.057265, 0.881054, 0.740239],
|
||||
[0.676809, 0.615810, 0.439865, 0.382935],
|
||||
[0.685883, 0.602310, 0.430222, 0.352224],
|
||||
[0.460258, 0.272456, 0.408684, 0.227532],
|
||||
[0.438829, 0.388352, 0.298733, 0.247999],
|
||||
[0.206406, 0.186191, 0.186191, 0.159779],
|
||||
[0.560763, 0.491939, 0.491939, 0.402013],
|
||||
[1.548721, 1.320138, 1.320138, 1.021469],
|
||||
[0.921232, 0.799827, 0.399914, 0.320599],
|
||||
[0.168333, 0.142587, 0.101848, 0.078692]])
|
||||
self.system_type = SystemType.singleTilt
|
||||
self.module_type = ModuleType.Cell96
|
||||
self.values.max_system_pressure.return_value = 1000
|
||||
self.values.system_type.return_value = self.system_type
|
||||
self.values.anchor_type.return_value = AnchorType.OMG_PowerGrip
|
||||
self.values.module_system_constants.return_value = self.system_type.module_constants(self.module_type)
|
||||
self.q_z = 70.155851
|
||||
self.subject = BallastCalculator(self.values)
|
||||
|
||||
def test_exceeding_maximal_uplift(self):
|
||||
expected = [PanelWarnings.MaxPsf]
|
||||
for i in range(0,1):
|
||||
actual = self.subject.ballast_tray_and_anchor_count(i, PanelType.Middle, 14, 100, self.c_p_matrix, self.q_z)
|
||||
assert_array_equal(expected, actual.warnings)
|
||||
|
||||
def test_not_exceeding_maximal_uplift(self):
|
||||
expected = []
|
||||
for i in range(2,7):
|
||||
actual = self.subject.ballast_tray_and_anchor_count(i, PanelType.Middle, 14, 100, self.c_p_matrix, self.q_z)
|
||||
assert_array_equal(expected, actual.warnings)
|
||||
Reference in New Issue
Block a user