Skip to content

Commit 49c192c

Browse files
Modify reporting of principal shear centre; include tests
1 parent 06c8f40 commit 49c192c

File tree

12 files changed

+387
-98
lines changed

12 files changed

+387
-98
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
# Change Log:
3+
4+
## v1.0.0:
5+
6+
Initial release.

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2017 Robbie van Leeuwen
3+
Copyright (c) 2018 Robbie van Leeuwen
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
include README.md
2+
include CHANGELOG.md

README.md

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,3 @@ $ pip install sectionproperties
9494
- [ ] Optimisation
9595
- [ ] Reinforced Concrete
9696
- [ ] Steel
97-
98-
## Change Log:
99-
100-
### v1.0.0:
101-
102-
Initial release.

docs/source/rst/examples.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -710,8 +710,8 @@ The following is printed to the terminal:
710710
y_se = 2.863400e+02
711711
x_st = 8.250070e+01
712712
y_st = 2.857074e+02
713-
x1_se = 8.250071e+01
714-
y2_se = 2.863400e+02
713+
x1_se = 7.063407e-04
714+
y2_se = 1.012091e+02
715715
A_sx = 1.104723e+04
716716
A_sy = 1.021183e+04
717717
A_s11 = 1.104723e+04

docs/source/rst/structure.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,8 @@ method::
157157
y_se = 1.000000e+02
158158
x_st = -2.505109e+01
159159
y_st = 1.000000e+02
160-
x1_se = -2.505109e+01
161-
y2_se = 1.000000e+02
160+
x1_se = -4.944543e+01
161+
y2_se = 4.905074e-06
162162
A_sx = 9.468851e+02
163163
A_sy = 1.106943e+03
164164
x_pc = 1.425046e+01

docs/source/rst/theory.rst

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ Theoretical Background
33

44
*coming soon...*
55

6-
.. # TODO: implement
7-
86
.. Mention that Poisson's ratios should be relatively close as if the Poisson’s
97
ratio is largely variable, the basic contention that sig_x = sig_y = sig_xy = 0
108
ceases to be applicable.

sectionproperties/analysis/cross_section.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1318,9 +1318,8 @@ def get_sc_p(self):
13181318
if self.section_props.x11_se is None:
13191319
return (None, None)
13201320
else:
1321-
# add centroid location to move section back to original location
1322-
x11_se = self.section_props.x11_se + self.section_props.cx
1323-
y22_se = self.section_props.y22_se + self.section_props.cy
1321+
x11_se = self.section_props.x11_se
1322+
y22_se = self.section_props.y22_se
13241323

13251324
return (x11_se, y22_se)
13261325

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import numpy as np
2+
3+
4+
def validate_properties(test, validation_list, section):
5+
"""a"""
6+
7+
for entry in validation_list:
8+
if entry["tol"] is None:
9+
tol = 1e-5
10+
else:
11+
tol = entry["tol"]
12+
13+
if entry["prop"] == "area":
14+
val = section.get_area()
15+
elif entry["prop"] == "ea":
16+
val = section.get_ea()
17+
elif entry["prop"] == "qx":
18+
(val, _) = section.get_q()
19+
elif entry["prop"] == "qy":
20+
(_, val) = section.get_q()
21+
elif entry["prop"] == "cx":
22+
(val, _) = section.get_c()
23+
elif entry["prop"] == "cy":
24+
(_, val) = section.get_c()
25+
elif entry["prop"] == "ixx_g":
26+
(val, _, _) = section.get_ig()
27+
elif entry["prop"] == "iyy_g":
28+
(_, val, _) = section.get_ig()
29+
elif entry["prop"] == "ixy_g":
30+
(_, _, val) = section.get_ig()
31+
elif entry["prop"] == "ixx_c":
32+
(val, _, _) = section.get_ic()
33+
elif entry["prop"] == "iyy_c":
34+
(_, val, _) = section.get_ic()
35+
elif entry["prop"] == "ixy_c":
36+
(_, _, val) = section.get_ic()
37+
elif entry["prop"] == "zxx_plus":
38+
(val, _, _, _) = section.get_z()
39+
elif entry["prop"] == "zxx_minus":
40+
(_, val, _, _) = section.get_z()
41+
elif entry["prop"] == "zyy_plus":
42+
(_, _, val, _) = section.get_z()
43+
elif entry["prop"] == "zyy_minus":
44+
(_, _, _, val) = section.get_z()
45+
elif entry["prop"] == "rx":
46+
(val, _) = section.get_rc()
47+
elif entry["prop"] == "ry":
48+
(_, val) = section.get_rc()
49+
elif entry["prop"] == "phi":
50+
val = section.get_phi()
51+
elif entry["prop"] == "i11_c":
52+
(val, _) = section.get_ip()
53+
elif entry["prop"] == "i22_c":
54+
(_, val) = section.get_ip()
55+
elif entry["prop"] == "z11_plus":
56+
(val, _, _, _) = section.get_zp()
57+
elif entry["prop"] == "z11_minus":
58+
(_, val, _, _) = section.get_zp()
59+
elif entry["prop"] == "z22_plus":
60+
(_, _, val, _) = section.get_zp()
61+
elif entry["prop"] == "z22_minus":
62+
(_, _, _, val) = section.get_zp()
63+
elif entry["prop"] == "r11":
64+
(val, _) = section.get_rp()
65+
elif entry["prop"] == "r22":
66+
(_, val) = section.get_rp()
67+
elif entry["prop"] == "x_pc":
68+
(val, _) = section.get_pc()
69+
elif entry["prop"] == "y_pc":
70+
(_, val) = section.get_pc()
71+
elif entry["prop"] == "x11_pc":
72+
(val, _) = section.get_pc_p()
73+
elif entry["prop"] == "y22_pc":
74+
(_, val) = section.get_pc_p()
75+
elif entry["prop"] == "sxx":
76+
(val, _) = section.get_s()
77+
elif entry["prop"] == "syy":
78+
(_, val) = section.get_s()
79+
elif entry["prop"] == "s11":
80+
(val, _) = section.get_sp()
81+
elif entry["prop"] == "s22":
82+
(_, val) = section.get_sp()
83+
elif entry["prop"] == "sf_xx_plus":
84+
(val, _, _, _) = section.get_sf()
85+
elif entry["prop"] == "sf_xx_minus":
86+
(_, val, _, _) = section.get_sf()
87+
elif entry["prop"] == "sf_yy_plus":
88+
(_, _, val, _) = section.get_sf()
89+
elif entry["prop"] == "sf_yy_minus":
90+
(_, _, _, val) = section.get_sf()
91+
elif entry["prop"] == "sf_11_plus":
92+
(val, _, _, _) = section.get_sf_p()
93+
elif entry["prop"] == "sf_11_minus":
94+
(_, val, _, _) = section.get_sf_p()
95+
elif entry["prop"] == "sf_22_plus":
96+
(_, _, val, _) = section.get_sf_p()
97+
elif entry["prop"] == "sf_22_minus":
98+
(_, _, _, val) = section.get_sf_p()
99+
elif entry["prop"] == "j":
100+
val = section.get_j()
101+
elif entry["prop"] == "gamma":
102+
val = section.get_gamma()
103+
elif entry["prop"] == "A_s11":
104+
(val, _) = section.get_As_p()
105+
elif entry["prop"] == "A_s22":
106+
(_, val) = section.get_As_p()
107+
elif entry["prop"] == "x11_se":
108+
(val, _) = section.get_sc_p()
109+
elif entry["prop"] == "y22_se":
110+
(_, val) = section.get_sc_p()
111+
else:
112+
raise KeyError("Incorrect property key: {0}".format(entry["prop"]))
113+
114+
if entry["val"] != 0:
115+
calc_tol = (val - entry["val"]) / entry["val"]
116+
else:
117+
calc_tol = val - entry["val"]
118+
119+
test.assertTrue(np.isclose(val, entry["val"], rtol=tol),
120+
msg="Prop: {0}; Tol: {1:.5e}".format(
121+
entry["prop"], calc_tol))

sectionproperties/tests/test_rectangle.py

Lines changed: 94 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
import unittest
2-
import numpy as np
32
import sectionproperties.pre.sections as sections
43
from sectionproperties.analysis.cross_section import CrossSection
4+
from sectionproperties.tests.helper_functions import validate_properties
55

66

77
class TestRectangle(unittest.TestCase):
8+
"""Section properties are mostly validated against hand calcs. Results from
9+
Strand7 and Roark's Formulas for Stress and Strain are used for some
10+
warping properties."""
11+
812
def setUp(self):
913
self.geometry = sections.RectangularSection(d=100, b=50)
1014
self.mesh = self.geometry.create_mesh(mesh_sizes=[10])
@@ -13,97 +17,105 @@ def setUp(self):
1317
def test_geometric(self):
1418
self.section.calculate_geometric_properties()
1519

16-
self.assertAlmostEqual(self.section.get_area(), 100 * 50)
17-
self.assertAlmostEqual(self.section.get_ea(), 1 * 100 * 50)
18-
(qx, qy) = self.section.get_q()
19-
self.assertAlmostEqual(qx, 100 * 50 * 50)
20-
self.assertAlmostEqual(qy, 100 * 50 * 25)
21-
(ixx_g, iyy_g, ixy_g) = self.section.get_ig()
22-
self.assertAlmostEqual(ixx_g, 50 * 100 ** 3 / 3)
23-
self.assertAlmostEqual(iyy_g, 100 * 50 ** 3 / 3)
24-
self.assertAlmostEqual(ixy_g, 100 * 50 * 50 * 25)
25-
(cx, cy) = self.section.get_c()
26-
self.assertAlmostEqual(cx, 50 / 2)
27-
self.assertAlmostEqual(cy, 100 / 2)
28-
(ixx_c, iyy_c, ixy_c) = self.section.get_ic()
29-
self.assertAlmostEqual(ixx_c, 50 * 100 ** 3 / 12)
30-
self.assertAlmostEqual(iyy_c, 100 * 50 ** 3 / 12)
31-
self.assertAlmostEqual(ixy_c, 0)
32-
(zxx_plus, zxx_minus, zyy_plus, zyy_minus) = self.section.get_z()
33-
self.assertAlmostEqual(zxx_plus, 50 * 100 ** 2 / 6)
34-
self.assertAlmostEqual(zxx_minus, 50 * 100 ** 2 / 6)
35-
self.assertAlmostEqual(zyy_plus, 100 * 50 ** 2 / 6)
36-
self.assertAlmostEqual(zyy_minus, 100 * 50 ** 2 / 6)
37-
(rx, ry) = self.section.get_rc()
38-
self.assertAlmostEqual(rx, (50 * 100 ** 3 / 12 / 100 / 50) ** 0.5)
39-
self.assertAlmostEqual(ry, (100 * 50 ** 3 / 12 / 100 / 50) ** 0.5)
40-
(i11_c, i22_c) = self.section.get_ip()
41-
self.assertAlmostEqual(i11_c, 50 * 100 ** 3 / 12)
42-
self.assertAlmostEqual(i22_c, 100 * 50 ** 3 / 12)
43-
phi = self.section.get_phi()
44-
self.assertAlmostEqual(phi, 0)
45-
(z11_plus, z11_minus, z22_plus, z22_minus) = self.section.get_zp()
46-
self.assertAlmostEqual(z11_plus, 50 * 100 ** 2 / 6)
47-
self.assertAlmostEqual(z11_minus, 50 * 100 ** 2 / 6)
48-
self.assertAlmostEqual(z22_plus, 100 * 50 ** 2 / 6)
49-
self.assertAlmostEqual(z22_minus, 100 * 50 ** 2 / 6)
50-
(r11, r22) = self.section.get_rp()
51-
self.assertAlmostEqual(r11, (50 * 100 ** 3 / 12 / 100 / 50) ** 0.5)
52-
self.assertAlmostEqual(r22, (100 * 50 ** 3 / 12 / 100 / 50) ** 0.5)
20+
val_list = []
21+
val_list.append({"prop": "area", "val": 100 * 50, "tol": None})
22+
val_list.append({"prop": "ea", "val": 1 * 100 * 50, "tol": None})
23+
val_list.append({"prop": "qx", "val": 100 * 50 * 50, "tol": None})
24+
val_list.append({"prop": "qy", "val": 100 * 50 * 25, "tol": None})
25+
val_list.append({"prop": "ixx_g", "val": 50 * 100 ** 3 / 3,
26+
"tol": None})
27+
val_list.append({"prop": "iyy_g", "val": 100 * 50 ** 3 / 3,
28+
"tol": None})
29+
val_list.append({"prop": "ixy_g", "val": 100 * 50 * 50 * 25,
30+
"tol": None})
31+
val_list.append({"prop": "cx", "val": 50 / 2, "tol": None})
32+
val_list.append({"prop": "cy", "val": 100 / 2, "tol": None})
33+
val_list.append({"prop": "ixx_c", "val": 50 * 100 ** 3 / 12,
34+
"tol": None})
35+
val_list.append({"prop": "iyy_c", "val": 100 * 50 ** 3 / 12,
36+
"tol": None})
37+
val_list.append({"prop": "ixy_c", "val": 0, "tol": None})
38+
val_list.append({"prop": "zxx_plus", "val": 50 * 100 ** 2 / 6,
39+
"tol": None})
40+
val_list.append({"prop": "zxx_minus", "val": 50 * 100 ** 2 / 6,
41+
"tol": None})
42+
val_list.append({"prop": "zyy_plus", "val": 100 * 50 ** 2 / 6,
43+
"tol": None})
44+
val_list.append({"prop": "zyy_minus", "val": 100 * 50 ** 2 / 6,
45+
"tol": None})
46+
val_list.append({"prop": "rx",
47+
"val": (50 * 100 ** 3 / 12 / 100 / 50) ** 0.5,
48+
"tol": None})
49+
val_list.append({"prop": "ry",
50+
"val": (100 * 50 ** 3 / 12 / 100 / 50) ** 0.5,
51+
"tol": None})
52+
val_list.append({"prop": "i11_c", "val": 50 * 100 ** 3 / 12,
53+
"tol": None})
54+
val_list.append({"prop": "i22_c", "val": 100 * 50 ** 3 / 12,
55+
"tol": None})
56+
val_list.append({"prop": "phi", "val": 0, "tol": None})
57+
val_list.append({"prop": "z11_plus", "val": 50 * 100 ** 2 / 6,
58+
"tol": None})
59+
val_list.append({"prop": "z11_minus", "val": 50 * 100 ** 2 / 6,
60+
"tol": None})
61+
val_list.append({"prop": "z22_plus", "val": 100 * 50 ** 2 / 6,
62+
"tol": None})
63+
val_list.append({"prop": "z22_minus", "val": 100 * 50 ** 2 / 6,
64+
"tol": None})
65+
val_list.append({"prop": "r11",
66+
"val": (50 * 100 ** 3 / 12 / 100 / 50) ** 0.5,
67+
"tol": None})
68+
val_list.append({"prop": "r22",
69+
"val": (100 * 50 ** 3 / 12 / 100 / 50) ** 0.5,
70+
"tol": None})
71+
72+
validate_properties(self, val_list, self.section)
5373

5474
def test_plastic(self):
5575
self.section.calculate_geometric_properties()
5676
self.section.calculate_plastic_properties()
5777

58-
(x_pc, y_pc) = self.section.get_pc()
59-
self.assertTrue(np.isclose(x_pc, 50 / 2))
60-
self.assertTrue(np.isclose(y_pc, 100 / 2))
61-
(x11_pc, y22_pc) = self.section.get_pc_p()
62-
self.assertTrue(np.isclose(x11_pc, 50 / 2))
63-
self.assertTrue(np.isclose(y22_pc, 100 / 2))
64-
(sxx, syy) = self.section.get_s()
65-
self.assertTrue(np.isclose(sxx, 50 * 100 ** 2 / 4))
66-
self.assertTrue(np.isclose(syy, 100 * 50 ** 2 / 4))
67-
(s11, s22) = self.section.get_sp()
68-
self.assertTrue(np.isclose(s11, 50 * 100 ** 2 / 4))
69-
self.assertTrue(np.isclose(s22, 100 * 50 ** 2 / 4))
70-
(sf_xx_plus, sf_xx_minus, sf_yy_plus,
71-
sf_yy_minus) = self.section.get_sf()
72-
self.assertTrue(np.isclose(sf_xx_plus, 1.5))
73-
self.assertTrue(np.isclose(sf_xx_minus, 1.5))
74-
self.assertTrue(np.isclose(sf_yy_plus, 1.5))
75-
self.assertTrue(np.isclose(sf_yy_minus, 1.5))
76-
(sf_11_plus, sf_11_minus, sf_22_plus,
77-
sf_22_minus) = self.section.get_sf_p()
78-
self.assertTrue(np.isclose(sf_11_plus, 1.5))
79-
self.assertTrue(np.isclose(sf_11_minus, 1.5))
80-
self.assertTrue(np.isclose(sf_22_plus, 1.5))
81-
self.assertTrue(np.isclose(sf_22_minus, 1.5))
78+
val_list = []
79+
val_list.append({"prop": "x_pc", "val": 50 / 2, "tol": None})
80+
val_list.append({"prop": "y_pc", "val": 100 / 2, "tol": None})
81+
val_list.append({"prop": "x11_pc", "val": 50 / 2, "tol": None})
82+
val_list.append({"prop": "y22_pc", "val": 100 / 2, "tol": None})
83+
val_list.append({"prop": "sxx", "val": 50 * 100 ** 2 / 4, "tol": None})
84+
val_list.append({"prop": "syy", "val": 100 * 50 ** 2 / 4, "tol": None})
85+
val_list.append({"prop": "s11", "val": 50 * 100 ** 2 / 4, "tol": None})
86+
val_list.append({"prop": "s22", "val": 100 * 50 ** 2 / 4, "tol": None})
87+
val_list.append({"prop": "sf_xx_plus", "val": 1.5, "tol": None})
88+
val_list.append({"prop": "sf_xx_minus", "val": 1.5, "tol": None})
89+
val_list.append({"prop": "sf_yy_plus", "val": 1.5, "tol": None})
90+
val_list.append({"prop": "sf_yy_minus", "val": 1.5, "tol": None})
91+
val_list.append({"prop": "sf_11_plus", "val": 1.5, "tol": None})
92+
val_list.append({"prop": "sf_11_minus", "val": 1.5, "tol": None})
93+
val_list.append({"prop": "sf_22_plus", "val": 1.5, "tol": None})
94+
val_list.append({"prop": "sf_22_minus", "val": 1.5, "tol": None})
95+
96+
validate_properties(self, val_list, self.section)
8297

8398
def test_warping(self):
8499
self.section.calculate_geometric_properties()
85100
self.section.calculate_warping_properties()
86101

87-
j = self.section.get_j()
88-
self.assertTrue(np.isclose(j, 2861002, rtol=0.05, atol=0)) # roarks
89-
# TODO: add Strand7 check and more resources?
90-
(x_se, y_se) = self.section.get_sc()
91-
self.assertTrue(np.isclose(x_se, 50 / 2))
92-
self.assertTrue(np.isclose(y_se, 100 / 2))
93-
(x11_se, y22_se) = self.section.get_sc_p()
94-
self.assertTrue(np.isclose(x11_se, 50 / 2))
95-
self.assertTrue(np.isclose(y22_se, 100 / 2))
96-
(x_st, y_st) = self.section.get_sc_t()
97-
self.assertTrue(np.isclose(x_st, 50 / 2))
98-
self.assertTrue(np.isclose(y_st, 100 / 2))
99-
gamma = self.section.get_gamma()
100-
# TODO: check gamma
101-
(A_sx, A_sy) = self.section.get_As()
102-
self.assertTrue(np.isclose(A_sx, 5 / 6 * 100 * 50))
103-
self.assertTrue(np.isclose(A_sy, 5 / 6 * 100 * 50))
104-
(A_s11, A_s22) = self.section.get_As_p()
105-
self.assertTrue(np.isclose(A_s11, 5 / 6 * 100 * 50))
106-
self.assertTrue(np.isclose(A_s22, 5 / 6 * 100 * 50))
102+
val_list = []
103+
val_list.append({"prop": "j", "val": 2861002, "tol": 0.04}) # roark's
104+
val_list.append({"prop": "j", "val": 2.85852e6, "tol": 2e-5}) # st7
105+
val_list.append({"prop": "gamma", "val": 3.17542e8,
106+
"tol": None}) # st7
107+
val_list.append({"prop": "x_se", "val": 50 / 2, "tol": None})
108+
val_list.append({"prop": "y_se", "val": 100 / 2, "tol": None})
109+
val_list.append({"prop": "x11_se", "val": 0, "tol": None})
110+
val_list.append({"prop": "y22_se", "val": 0, "tol": None})
111+
val_list.append({"prop": "x_st", "val": 50 / 2, "tol": None})
112+
val_list.append({"prop": "y_st", "val": 100 / 2, "tol": None})
113+
val_list.append({"prop": "A_sx", "val": 5 / 6 * 100 * 50, "tol": None})
114+
val_list.append({"prop": "A_sy", "val": 5 / 6 * 100 * 50, "tol": None})
115+
val_list.append({"prop": "A_s11", "val": 5 / 6 * 100 * 50,
116+
"tol": None})
117+
val_list.append({"prop": "A_s22", "val": 5 / 6 * 100 * 50,
118+
"tol": None})
107119

108120

109121
if __name__ == "__main__":

0 commit comments

Comments
 (0)