PyNiteFEA 2.3.0__tar.gz → 2.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pynitefea-2.3.0 → pynitefea-2.4.0}/PKG-INFO +5 -2
- {pynitefea-2.3.0 → pynitefea-2.4.0}/PyNiteFEA.egg-info/PKG-INFO +5 -2
- {pynitefea-2.3.0 → pynitefea-2.4.0}/Pynite/Member3D.py +131 -95
- {pynitefea-2.3.0 → pynitefea-2.4.0}/Pynite/PhysMember.py +310 -76
- {pynitefea-2.3.0 → pynitefea-2.4.0}/Pynite/Visualization.py +3 -6
- {pynitefea-2.3.0 → pynitefea-2.4.0}/README.md +4 -1
- {pynitefea-2.3.0 → pynitefea-2.4.0}/setup.py +1 -1
- {pynitefea-2.3.0 → pynitefea-2.4.0}/LICENSE +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/PyNiteFEA.egg-info/SOURCES.txt +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/PyNiteFEA.egg-info/dependency_links.txt +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/PyNiteFEA.egg-info/requires.txt +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/PyNiteFEA.egg-info/top_level.txt +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/Pynite/Analysis.py +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/Pynite/BeamSegY.py +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/Pynite/BeamSegZ.py +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/Pynite/FEModel3D.py +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/Pynite/FixedEndReactions.py +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/Pynite/LoadCombo.py +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/Pynite/MainStyleSheet.css +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/Pynite/MatFoundation.py +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/Pynite/Material.py +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/Pynite/Mesh.py +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/Pynite/Node3D.py +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/Pynite/Plate3D.py +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/Pynite/Quad3D.py +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/Pynite/Rendering.py +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/Pynite/Report_Template.html +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/Pynite/Reporting.py +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/Pynite/Section.py +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/Pynite/ShearWall.py +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/Pynite/Spring3D.py +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/Pynite/Tri3D.py +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/Pynite/VTKWriter.py +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/Pynite/__init__.py +0 -0
- {pynitefea-2.3.0 → pynitefea-2.4.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyNiteFEA
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.0
|
|
4
4
|
Summary: A simple elastic 3D structural finite element library for Python.
|
|
5
5
|
Home-page: https://github.com/JWock82/Pynite.git
|
|
6
6
|
Author: D. Craig Brinck, PE, SE
|
|
@@ -121,9 +121,12 @@ Here's a list of projects that use Pynite:
|
|
|
121
121
|
* Phaenotyp (https://github.com/bewegende-Architektur/Phaenotyp) (https://youtu.be/shloSw9HjVI)
|
|
122
122
|
|
|
123
123
|
# What's New?
|
|
124
|
+
2.4.0
|
|
125
|
+
* Member `max` and `min` methods now return governing load combination along with the member max/min forces.
|
|
126
|
+
* Bug fix: Quadrilateral element displacements had corners swapped during VTK visualization. This was a relic from the old MITC4 formulation that has been corrected.
|
|
127
|
+
|
|
124
128
|
v2.3.0
|
|
125
129
|
* Added enveloping to member diagrams. Set `combo_name` to a list of combo tags and the member diagram will show an envelope of all the combos that have any of those tags.
|
|
126
|
-
* Bug fix: Quadrilateral element displacements had corners swapped during VTK visualization. This was a relic from the old MITC4 formulation that has been corrected.
|
|
127
130
|
* Bug fix: Added shear wall and mat foundation load cases to `FEModel3D.load_cases()`. The list of load cases was sometimes incomplete if these meshes had not yet been generated.
|
|
128
131
|
* Added bending moment end releases to visualizations.
|
|
129
132
|
* Bug fix for shear walls with flanges having an origin with their origin at Y != 0.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyNiteFEA
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.0
|
|
4
4
|
Summary: A simple elastic 3D structural finite element library for Python.
|
|
5
5
|
Home-page: https://github.com/JWock82/Pynite.git
|
|
6
6
|
Author: D. Craig Brinck, PE, SE
|
|
@@ -121,9 +121,12 @@ Here's a list of projects that use Pynite:
|
|
|
121
121
|
* Phaenotyp (https://github.com/bewegende-Architektur/Phaenotyp) (https://youtu.be/shloSw9HjVI)
|
|
122
122
|
|
|
123
123
|
# What's New?
|
|
124
|
+
2.4.0
|
|
125
|
+
* Member `max` and `min` methods now return governing load combination along with the member max/min forces.
|
|
126
|
+
* Bug fix: Quadrilateral element displacements had corners swapped during VTK visualization. This was a relic from the old MITC4 formulation that has been corrected.
|
|
127
|
+
|
|
124
128
|
v2.3.0
|
|
125
129
|
* Added enveloping to member diagrams. Set `combo_name` to a list of combo tags and the member diagram will show an envelope of all the combos that have any of those tags.
|
|
126
|
-
* Bug fix: Quadrilateral element displacements had corners swapped during VTK visualization. This was a relic from the old MITC4 formulation that has been corrected.
|
|
127
130
|
* Bug fix: Added shear wall and mat foundation load cases to `FEModel3D.load_cases()`. The list of load cases was sometimes incomplete if these meshes had not yet been generated.
|
|
128
131
|
* Added bending moment end releases to visualizations.
|
|
129
132
|
* Bug fix for shear walls with flanges having an origin with their origin at Y != 0.
|
|
@@ -1154,7 +1154,7 @@ class Member3D():
|
|
|
1154
1154
|
|
|
1155
1155
|
return 0
|
|
1156
1156
|
|
|
1157
|
-
def max_shear(self, Direction: Literal['Fy', 'Fz'], combo_tags: Union[str, List[str]] = 'Combo 1') -> float:
|
|
1157
|
+
def max_shear(self, Direction: Literal['Fy', 'Fz'], combo_tags: Union[str, List[str]] = 'Combo 1') -> Union[float, tuple[float, str]]:
|
|
1158
1158
|
"""
|
|
1159
1159
|
Returns the maximum shear force in the member for the specified direction
|
|
1160
1160
|
and load combination(s).
|
|
@@ -1174,16 +1174,10 @@ class Member3D():
|
|
|
1174
1174
|
|
|
1175
1175
|
Returns
|
|
1176
1176
|
-------
|
|
1177
|
-
float
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
Notes
|
|
1183
|
-
-----
|
|
1184
|
-
- Unlike moments, shear does not depend on P-Delta effects.
|
|
1185
|
-
- Automatically segments the member if it has not yet been segmented
|
|
1186
|
-
for a load combination.
|
|
1177
|
+
float or tuple of (float, str)
|
|
1178
|
+
If a single combo name is provided, returns the maximum shear value.
|
|
1179
|
+
If a list of tags is provided, returns a tuple of the maximum shear
|
|
1180
|
+
value and the name of the governing load combination.
|
|
1187
1181
|
"""
|
|
1188
1182
|
# Normalize input: single name vs list of tags
|
|
1189
1183
|
if isinstance(combo_tags, str):
|
|
@@ -1196,6 +1190,7 @@ class Member3D():
|
|
|
1196
1190
|
]
|
|
1197
1191
|
|
|
1198
1192
|
Vmax_global = None # will store the global maximum across combos
|
|
1193
|
+
governing_combo = None
|
|
1199
1194
|
|
|
1200
1195
|
for combo_name in combo_names:
|
|
1201
1196
|
# Skip inactive combos
|
|
@@ -1219,11 +1214,16 @@ class Member3D():
|
|
|
1219
1214
|
# Update global maximum
|
|
1220
1215
|
if Vmax_global is None or Vmax > Vmax_global:
|
|
1221
1216
|
Vmax_global = Vmax
|
|
1217
|
+
governing_combo = combo_name
|
|
1222
1218
|
|
|
1223
|
-
# Return
|
|
1224
|
-
|
|
1219
|
+
# Return result
|
|
1220
|
+
if Vmax_global is None:
|
|
1221
|
+
Vmax_global = 0
|
|
1222
|
+
if isinstance(combo_tags, list):
|
|
1223
|
+
return (Vmax_global, governing_combo)
|
|
1224
|
+
return Vmax_global
|
|
1225
1225
|
|
|
1226
|
-
def min_shear(self, Direction: Literal['Fy', 'Fz'], combo_tags: Union[str, List[str]] = 'Combo 1') -> float:
|
|
1226
|
+
def min_shear(self, Direction: Literal['Fy', 'Fz'], combo_tags: Union[str, List[str]] = 'Combo 1') -> Union[float, tuple[float, str]]:
|
|
1227
1227
|
"""
|
|
1228
1228
|
Returns the minimum shear force in the member for the specified direction
|
|
1229
1229
|
and load combination(s).
|
|
@@ -1243,16 +1243,10 @@ class Member3D():
|
|
|
1243
1243
|
|
|
1244
1244
|
Returns
|
|
1245
1245
|
-------
|
|
1246
|
-
float
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
Notes
|
|
1252
|
-
-----
|
|
1253
|
-
- Unlike moments, shear does not depend on P-Delta effects.
|
|
1254
|
-
- Automatically segments the member if it has not yet been segmented
|
|
1255
|
-
for a load combination.
|
|
1246
|
+
float or tuple of (float, str)
|
|
1247
|
+
If a single combo name is provided, returns the minimum shear value.
|
|
1248
|
+
If a list of tags is provided, returns a tuple of the minimum shear
|
|
1249
|
+
value and the name of the governing load combination.
|
|
1256
1250
|
"""
|
|
1257
1251
|
# Normalize input: single name vs list of tags
|
|
1258
1252
|
if isinstance(combo_tags, str):
|
|
@@ -1265,6 +1259,7 @@ class Member3D():
|
|
|
1265
1259
|
]
|
|
1266
1260
|
|
|
1267
1261
|
Vmin_global = None # will store the global minimum across combos
|
|
1262
|
+
governing_combo = None
|
|
1268
1263
|
|
|
1269
1264
|
for combo_name in combo_names:
|
|
1270
1265
|
# Skip inactive combos
|
|
@@ -1288,9 +1283,14 @@ class Member3D():
|
|
|
1288
1283
|
# Update global minimum
|
|
1289
1284
|
if Vmin_global is None or Vmin < Vmin_global:
|
|
1290
1285
|
Vmin_global = Vmin
|
|
1286
|
+
governing_combo = combo_name
|
|
1291
1287
|
|
|
1292
|
-
# Return
|
|
1293
|
-
|
|
1288
|
+
# Return result
|
|
1289
|
+
if Vmin_global is None:
|
|
1290
|
+
Vmin_global = 0
|
|
1291
|
+
if isinstance(combo_tags, list):
|
|
1292
|
+
return (Vmin_global, governing_combo)
|
|
1293
|
+
return Vmin_global
|
|
1294
1294
|
|
|
1295
1295
|
def plot_shear(self, Direction: Literal['Fy', 'Fz'], combo_name: Union[str, List[str]] = 'Combo 1', n_points: int = 20) -> None:
|
|
1296
1296
|
"""
|
|
@@ -1456,7 +1456,7 @@ class Member3D():
|
|
|
1456
1456
|
|
|
1457
1457
|
return 0
|
|
1458
1458
|
|
|
1459
|
-
def max_moment(self, Direction: Literal['My', 'Mz'], combo_tags: Union[str, List[str]] = 'Combo 1') -> float:
|
|
1459
|
+
def max_moment(self, Direction: Literal['My', 'Mz'], combo_tags: Union[str, List[str]] = 'Combo 1') -> Union[float, tuple[float, str]]:
|
|
1460
1460
|
"""
|
|
1461
1461
|
Returns the maximum bending moment in the member for the specified direction
|
|
1462
1462
|
and load combination(s).
|
|
@@ -1476,16 +1476,10 @@ class Member3D():
|
|
|
1476
1476
|
|
|
1477
1477
|
Returns
|
|
1478
1478
|
-------
|
|
1479
|
-
float
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
Notes
|
|
1485
|
-
-----
|
|
1486
|
-
- Includes P-Delta effects if the model's solution is 'P-Delta' or 'Pushover'.
|
|
1487
|
-
- Automatically segments the member if it has not yet been segmented
|
|
1488
|
-
for a load combination.
|
|
1479
|
+
float or tuple of (float, str)
|
|
1480
|
+
If a single combo name is provided, returns the maximum moment value.
|
|
1481
|
+
If a list of tags is provided, returns a tuple of the maximum moment
|
|
1482
|
+
value and the name of the governing load combination.
|
|
1489
1483
|
"""
|
|
1490
1484
|
# Normalize input: single name vs list of tags
|
|
1491
1485
|
if isinstance(combo_tags, str):
|
|
@@ -1498,6 +1492,7 @@ class Member3D():
|
|
|
1498
1492
|
]
|
|
1499
1493
|
|
|
1500
1494
|
Mmax_global = None # will store the global maximum across combos
|
|
1495
|
+
governing_combo = None
|
|
1501
1496
|
|
|
1502
1497
|
for combo_name in combo_names:
|
|
1503
1498
|
# Skip inactive combos
|
|
@@ -1524,11 +1519,16 @@ class Member3D():
|
|
|
1524
1519
|
# Update global maximum
|
|
1525
1520
|
if Mmax_global is None or Mmax > Mmax_global:
|
|
1526
1521
|
Mmax_global = Mmax
|
|
1522
|
+
governing_combo = combo_name
|
|
1527
1523
|
|
|
1528
|
-
# Return
|
|
1529
|
-
|
|
1524
|
+
# Return result
|
|
1525
|
+
if Mmax_global is None:
|
|
1526
|
+
Mmax_global = 0
|
|
1527
|
+
if isinstance(combo_tags, list):
|
|
1528
|
+
return (Mmax_global, governing_combo)
|
|
1529
|
+
return Mmax_global
|
|
1530
1530
|
|
|
1531
|
-
def min_moment(self, Direction: Literal['My', 'Mz'], combo_tags: Union[str, List[str]] = 'Combo 1') -> float:
|
|
1531
|
+
def min_moment(self, Direction: Literal['My', 'Mz'], combo_tags: Union[str, List[str]] = 'Combo 1') -> Union[float, tuple[float, str]]:
|
|
1532
1532
|
"""
|
|
1533
1533
|
Returns the minimum bending moment in the member for the specified direction
|
|
1534
1534
|
and load combination(s).
|
|
@@ -1548,16 +1548,10 @@ class Member3D():
|
|
|
1548
1548
|
|
|
1549
1549
|
Returns
|
|
1550
1550
|
-------
|
|
1551
|
-
float
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
Notes
|
|
1557
|
-
-----
|
|
1558
|
-
- Includes P-Delta effects if the model's solution is 'P-Delta' or 'Pushover'.
|
|
1559
|
-
- Automatically segments the member if it has not yet been segmented
|
|
1560
|
-
for a load combination.
|
|
1551
|
+
float or tuple of (float, str)
|
|
1552
|
+
If a single combo name is provided, returns the minimum moment value.
|
|
1553
|
+
If a list of tags is provided, returns a tuple of the minimum moment
|
|
1554
|
+
value and the name of the governing load combination.
|
|
1561
1555
|
"""
|
|
1562
1556
|
# Normalize input: single name vs list of tags
|
|
1563
1557
|
if isinstance(combo_tags, str):
|
|
@@ -1570,6 +1564,7 @@ class Member3D():
|
|
|
1570
1564
|
]
|
|
1571
1565
|
|
|
1572
1566
|
Mmin_global = None # will store the global minimum across combos
|
|
1567
|
+
governing_combo = None
|
|
1573
1568
|
|
|
1574
1569
|
for combo_name in combo_names:
|
|
1575
1570
|
# Skip inactive combos
|
|
@@ -1596,9 +1591,14 @@ class Member3D():
|
|
|
1596
1591
|
# Update global minimum
|
|
1597
1592
|
if Mmin_global is None or Mmin < Mmin_global:
|
|
1598
1593
|
Mmin_global = Mmin
|
|
1594
|
+
governing_combo = combo_name
|
|
1599
1595
|
|
|
1600
|
-
# Return
|
|
1601
|
-
|
|
1596
|
+
# Return result
|
|
1597
|
+
if Mmin_global is None:
|
|
1598
|
+
Mmin_global = 0
|
|
1599
|
+
if isinstance(combo_tags, list):
|
|
1600
|
+
return (Mmin_global, governing_combo)
|
|
1601
|
+
return Mmin_global
|
|
1602
1602
|
|
|
1603
1603
|
|
|
1604
1604
|
def plot_moment(self, Direction: Literal['My', 'Mz'], combo_name: Union[str, List[str]] = 'Combo 1', n_points: int = 20) -> None:
|
|
@@ -1747,7 +1747,7 @@ class Member3D():
|
|
|
1747
1747
|
|
|
1748
1748
|
return 0
|
|
1749
1749
|
|
|
1750
|
-
def max_torque(self, combo_tags: Union[str, List[str]] = 'Combo 1') -> float:
|
|
1750
|
+
def max_torque(self, combo_tags: Union[str, List[str]] = 'Combo 1') -> Union[float, tuple[float, str]]:
|
|
1751
1751
|
"""
|
|
1752
1752
|
Returns the maximum torsional moment in the member across the
|
|
1753
1753
|
specified load combination(s).
|
|
@@ -1763,10 +1763,10 @@ class Member3D():
|
|
|
1763
1763
|
|
|
1764
1764
|
Returns
|
|
1765
1765
|
-------
|
|
1766
|
-
float
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1766
|
+
float or tuple of (float, str)
|
|
1767
|
+
If a single combo name is provided, returns the maximum torsion value.
|
|
1768
|
+
If a list of tags is provided, returns a tuple of the maximum torsion
|
|
1769
|
+
value and the name of the governing load combination.
|
|
1770
1770
|
"""
|
|
1771
1771
|
# Normalize input: single combo name or list of tags
|
|
1772
1772
|
if isinstance(combo_tags, str):
|
|
@@ -1779,6 +1779,7 @@ class Member3D():
|
|
|
1779
1779
|
|
|
1780
1780
|
# Track global maximum torsion across all combos
|
|
1781
1781
|
Tmax_global = None
|
|
1782
|
+
governing_combo = None
|
|
1782
1783
|
|
|
1783
1784
|
# Loop through each candidate combo
|
|
1784
1785
|
for combo_name in combo_names:
|
|
@@ -1801,12 +1802,17 @@ class Member3D():
|
|
|
1801
1802
|
# Update global maximum
|
|
1802
1803
|
if Tmax_global is None or Tmax > Tmax_global:
|
|
1803
1804
|
Tmax_global = Tmax
|
|
1805
|
+
governing_combo = combo_name
|
|
1804
1806
|
|
|
1805
|
-
# Return
|
|
1806
|
-
|
|
1807
|
+
# Return result
|
|
1808
|
+
if Tmax_global is None:
|
|
1809
|
+
Tmax_global = 0
|
|
1810
|
+
if isinstance(combo_tags, list):
|
|
1811
|
+
return (Tmax_global, governing_combo)
|
|
1812
|
+
return Tmax_global
|
|
1807
1813
|
|
|
1808
1814
|
|
|
1809
|
-
def min_torque(self, combo_tags: Union[str, List[str]] = 'Combo 1') -> float:
|
|
1815
|
+
def min_torque(self, combo_tags: Union[str, List[str]] = 'Combo 1') -> Union[float, tuple[float, str]]:
|
|
1810
1816
|
"""
|
|
1811
1817
|
Returns the minimum torsional moment in the member across the
|
|
1812
1818
|
specified load combination(s).
|
|
@@ -1822,10 +1828,10 @@ class Member3D():
|
|
|
1822
1828
|
|
|
1823
1829
|
Returns
|
|
1824
1830
|
-------
|
|
1825
|
-
float
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1831
|
+
float or tuple of (float, str)
|
|
1832
|
+
If a single combo name is provided, returns the minimum torsion value.
|
|
1833
|
+
If a list of tags is provided, returns a tuple of the minimum torsion
|
|
1834
|
+
value and the name of the governing load combination.
|
|
1829
1835
|
"""
|
|
1830
1836
|
# Normalize input: single combo name or list of tags
|
|
1831
1837
|
if isinstance(combo_tags, str):
|
|
@@ -1838,6 +1844,7 @@ class Member3D():
|
|
|
1838
1844
|
|
|
1839
1845
|
# Track global minimum torsion across all combos
|
|
1840
1846
|
Tmin_global = None
|
|
1847
|
+
governing_combo = None
|
|
1841
1848
|
|
|
1842
1849
|
# Loop through each candidate combo
|
|
1843
1850
|
for combo_name in combo_names:
|
|
@@ -1860,9 +1867,14 @@ class Member3D():
|
|
|
1860
1867
|
# Update global minimum
|
|
1861
1868
|
if Tmin_global is None or Tmin < Tmin_global:
|
|
1862
1869
|
Tmin_global = Tmin
|
|
1870
|
+
governing_combo = combo_name
|
|
1863
1871
|
|
|
1864
|
-
# Return
|
|
1865
|
-
|
|
1872
|
+
# Return result
|
|
1873
|
+
if Tmin_global is None:
|
|
1874
|
+
Tmin_global = 0
|
|
1875
|
+
if isinstance(combo_tags, list):
|
|
1876
|
+
return (Tmin_global, governing_combo)
|
|
1877
|
+
return Tmin_global
|
|
1866
1878
|
|
|
1867
1879
|
def plot_torque(self, combo_name: Union[str, List[str]] = 'Combo 1', n_points: int = 20) -> None:
|
|
1868
1880
|
"""
|
|
@@ -1980,7 +1992,7 @@ class Member3D():
|
|
|
1980
1992
|
|
|
1981
1993
|
return 0
|
|
1982
1994
|
|
|
1983
|
-
def max_axial(self, combo_tags: Union[str, List[str]] = 'Combo 1') -> float:
|
|
1995
|
+
def max_axial(self, combo_tags: Union[str, List[str]] = 'Combo 1') -> Union[float, tuple[float, str]]:
|
|
1984
1996
|
"""
|
|
1985
1997
|
Returns the maximum axial force in the member across the specified
|
|
1986
1998
|
load combination(s).
|
|
@@ -1996,10 +2008,10 @@ class Member3D():
|
|
|
1996
2008
|
|
|
1997
2009
|
Returns
|
|
1998
2010
|
-------
|
|
1999
|
-
float
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2011
|
+
float or tuple of (float, str)
|
|
2012
|
+
If a single combo name is provided, returns the maximum axial value.
|
|
2013
|
+
If a list of tags is provided, returns a tuple of the maximum axial
|
|
2014
|
+
value and the name of the governing load combination.
|
|
2003
2015
|
"""
|
|
2004
2016
|
# Normalize input: if a string is passed, treat it as a single combo name
|
|
2005
2017
|
if isinstance(combo_tags, str):
|
|
@@ -2013,6 +2025,7 @@ class Member3D():
|
|
|
2013
2025
|
|
|
2014
2026
|
# Track the global maximum axial force across all combos
|
|
2015
2027
|
Pmax_global = None
|
|
2028
|
+
governing_combo = None
|
|
2016
2029
|
|
|
2017
2030
|
# Loop through each candidate combo
|
|
2018
2031
|
for combo_name in combo_names:
|
|
@@ -2035,11 +2048,16 @@ class Member3D():
|
|
|
2035
2048
|
# Update the global maximum
|
|
2036
2049
|
if Pmax_global is None or Pmax > Pmax_global:
|
|
2037
2050
|
Pmax_global = Pmax
|
|
2051
|
+
governing_combo = combo_name
|
|
2038
2052
|
|
|
2039
|
-
# Return
|
|
2040
|
-
|
|
2053
|
+
# Return result
|
|
2054
|
+
if Pmax_global is None:
|
|
2055
|
+
Pmax_global = 0
|
|
2056
|
+
if isinstance(combo_tags, list):
|
|
2057
|
+
return (Pmax_global, governing_combo)
|
|
2058
|
+
return Pmax_global
|
|
2041
2059
|
|
|
2042
|
-
def min_axial(self, combo_tags: Union[str, List[str]] = 'Combo 1') -> float:
|
|
2060
|
+
def min_axial(self, combo_tags: Union[str, List[str]] = 'Combo 1') -> Union[float, tuple[float, str]]:
|
|
2043
2061
|
"""
|
|
2044
2062
|
Returns the minimum axial force in the member across the specified
|
|
2045
2063
|
load combination(s).
|
|
@@ -2055,10 +2073,10 @@ class Member3D():
|
|
|
2055
2073
|
|
|
2056
2074
|
Returns
|
|
2057
2075
|
-------
|
|
2058
|
-
float
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2076
|
+
float or tuple of (float, str)
|
|
2077
|
+
If a single combo name is provided, returns the minimum axial value.
|
|
2078
|
+
If a list of tags is provided, returns a tuple of the minimum axial
|
|
2079
|
+
value and the name of the governing load combination.
|
|
2062
2080
|
"""
|
|
2063
2081
|
# Normalize input: if a string is passed, treat it as a single combo name
|
|
2064
2082
|
if isinstance(combo_tags, str):
|
|
@@ -2072,6 +2090,7 @@ class Member3D():
|
|
|
2072
2090
|
|
|
2073
2091
|
# Track the global minimum axial force across all combos
|
|
2074
2092
|
Pmin_global = None
|
|
2093
|
+
governing_combo = None
|
|
2075
2094
|
|
|
2076
2095
|
# Loop through each candidate combo
|
|
2077
2096
|
for combo_name in combo_names:
|
|
@@ -2094,9 +2113,14 @@ class Member3D():
|
|
|
2094
2113
|
# Update the global minimum
|
|
2095
2114
|
if Pmin_global is None or Pmin < Pmin_global:
|
|
2096
2115
|
Pmin_global = Pmin
|
|
2116
|
+
governing_combo = combo_name
|
|
2097
2117
|
|
|
2098
|
-
# Return
|
|
2099
|
-
|
|
2118
|
+
# Return result
|
|
2119
|
+
if Pmin_global is None:
|
|
2120
|
+
Pmin_global = 0
|
|
2121
|
+
if isinstance(combo_tags, list):
|
|
2122
|
+
return (Pmin_global, governing_combo)
|
|
2123
|
+
return Pmin_global
|
|
2100
2124
|
|
|
2101
2125
|
def plot_axial(self, combo_name: Union[str, List[str]] = 'Combo 1', n_points: int = 20) -> None:
|
|
2102
2126
|
"""
|
|
@@ -2257,7 +2281,7 @@ class Member3D():
|
|
|
2257
2281
|
|
|
2258
2282
|
return 0
|
|
2259
2283
|
|
|
2260
|
-
def max_deflection(self, Direction: Literal['dx', 'dy', 'dz'], combo_tags: Union[str, List[str]] = 'Combo 1') -> float:
|
|
2284
|
+
def max_deflection(self, Direction: Literal['dx', 'dy', 'dz'], combo_tags: Union[str, List[str]] = 'Combo 1') -> Union[float, tuple[float, str]]:
|
|
2261
2285
|
"""
|
|
2262
2286
|
Returns the maximum deflection in the member across the specified
|
|
2263
2287
|
load combination(s).
|
|
@@ -2278,10 +2302,10 @@ class Member3D():
|
|
|
2278
2302
|
|
|
2279
2303
|
Returns
|
|
2280
2304
|
-------
|
|
2281
|
-
float
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2305
|
+
float or tuple of (float, str)
|
|
2306
|
+
If a single combo name is provided, returns the maximum deflection.
|
|
2307
|
+
If a list of tags is provided, returns a tuple of the maximum
|
|
2308
|
+
deflection and the name of the governing load combination.
|
|
2285
2309
|
"""
|
|
2286
2310
|
# Normalize input: single name or list of tags
|
|
2287
2311
|
if isinstance(combo_tags, str):
|
|
@@ -2294,6 +2318,7 @@ class Member3D():
|
|
|
2294
2318
|
|
|
2295
2319
|
# Track global maximum deflection across all combos
|
|
2296
2320
|
dmax_global = None
|
|
2321
|
+
governing_combo = None
|
|
2297
2322
|
|
|
2298
2323
|
# Loop through each candidate combo
|
|
2299
2324
|
for combo_name in combo_names:
|
|
@@ -2318,12 +2343,17 @@ class Member3D():
|
|
|
2318
2343
|
# Update global maximum
|
|
2319
2344
|
if dmax_global is None or dmax > dmax_global:
|
|
2320
2345
|
dmax_global = dmax
|
|
2346
|
+
governing_combo = combo_name
|
|
2321
2347
|
|
|
2322
|
-
# Return
|
|
2323
|
-
|
|
2348
|
+
# Return result
|
|
2349
|
+
if dmax_global is None:
|
|
2350
|
+
dmax_global = 0
|
|
2351
|
+
if isinstance(combo_tags, list):
|
|
2352
|
+
return (dmax_global, governing_combo)
|
|
2353
|
+
return dmax_global
|
|
2324
2354
|
|
|
2325
2355
|
|
|
2326
|
-
def min_deflection(self, Direction: Literal['dx', 'dy', 'dz'], combo_tags: Union[str, List[str]] = 'Combo 1') -> float:
|
|
2356
|
+
def min_deflection(self, Direction: Literal['dx', 'dy', 'dz'], combo_tags: Union[str, List[str]] = 'Combo 1') -> Union[float, tuple[float, str]]:
|
|
2327
2357
|
"""
|
|
2328
2358
|
Returns the minimum deflection in the member across the specified
|
|
2329
2359
|
load combination(s).
|
|
@@ -2344,10 +2374,10 @@ class Member3D():
|
|
|
2344
2374
|
|
|
2345
2375
|
Returns
|
|
2346
2376
|
-------
|
|
2347
|
-
float
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2377
|
+
float or tuple of (float, str)
|
|
2378
|
+
If a single combo name is provided, returns the minimum deflection.
|
|
2379
|
+
If a list of tags is provided, returns a tuple of the minimum
|
|
2380
|
+
deflection and the name of the governing load combination.
|
|
2351
2381
|
"""
|
|
2352
2382
|
# Normalize input: single name or list of tags
|
|
2353
2383
|
if isinstance(combo_tags, str):
|
|
@@ -2360,6 +2390,7 @@ class Member3D():
|
|
|
2360
2390
|
|
|
2361
2391
|
# Track global minimum deflection across all combos
|
|
2362
2392
|
dmin_global = None
|
|
2393
|
+
governing_combo = None
|
|
2363
2394
|
|
|
2364
2395
|
# Loop through each candidate combo
|
|
2365
2396
|
for combo_name in combo_names:
|
|
@@ -2384,9 +2415,14 @@ class Member3D():
|
|
|
2384
2415
|
# Update global minimum
|
|
2385
2416
|
if dmin_global is None or dmin < dmin_global:
|
|
2386
2417
|
dmin_global = dmin
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2418
|
+
governing_combo = combo_name
|
|
2419
|
+
|
|
2420
|
+
# Return result
|
|
2421
|
+
if dmin_global is None:
|
|
2422
|
+
dmin_global = 0
|
|
2423
|
+
if isinstance(combo_tags, list):
|
|
2424
|
+
return (dmin_global, governing_combo)
|
|
2425
|
+
return dmin_global
|
|
2390
2426
|
|
|
2391
2427
|
def plot_deflection(self, Direction: Literal['dx', 'dy', 'dz'], combo_name: Union[str, List[str]] = 'Combo 1', n_points: int = 20) -> None:
|
|
2392
2428
|
"""
|
|
@@ -215,9 +215,9 @@ class PhysMember(Member3D):
|
|
|
215
215
|
member, x_mod = self.find_member(x)
|
|
216
216
|
return member.shear(Direction, x_mod, combo_name)
|
|
217
217
|
|
|
218
|
-
def max_shear(self, Direction: Literal['Fy', 'Fz'],
|
|
218
|
+
def max_shear(self, Direction: Literal['Fy', 'Fz'], combo_tags: Union[str, List[str]] = 'Combo 1') -> Union[float, tuple[float, str]]:
|
|
219
219
|
"""
|
|
220
|
-
Returns the maximum shear in the member for the given direction
|
|
220
|
+
Returns the maximum shear in the member for the given direction.
|
|
221
221
|
|
|
222
222
|
Parameters
|
|
223
223
|
----------
|
|
@@ -225,20 +225,41 @@ class PhysMember(Member3D):
|
|
|
225
225
|
The direction in which to find the maximum shear. Must be one of the following:
|
|
226
226
|
'Fy' = Shear acting on the local y-axis
|
|
227
227
|
'Fz' = Shear acting on the local z-axis
|
|
228
|
-
|
|
229
|
-
|
|
228
|
+
combo_tags : str or list of str
|
|
229
|
+
A single load combination name, or a list of combo tags.
|
|
230
|
+
|
|
231
|
+
Returns
|
|
232
|
+
-------
|
|
233
|
+
float or tuple of (float, str)
|
|
234
|
+
If a single combo name is provided, returns the maximum shear value.
|
|
235
|
+
If a list of tags is provided, returns a tuple of the maximum shear
|
|
236
|
+
value and the name of the governing load combination.
|
|
230
237
|
"""
|
|
231
238
|
|
|
239
|
+
if isinstance(combo_tags, str):
|
|
240
|
+
combo_names = [combo_tags]
|
|
241
|
+
else:
|
|
242
|
+
combo_names = [name for name, combo in self.model.load_combos.items()
|
|
243
|
+
if any(tag in combo.combo_tags for tag in combo_tags)]
|
|
244
|
+
|
|
232
245
|
Vmax = None
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
246
|
+
governing_combo = None
|
|
247
|
+
for name in combo_names:
|
|
248
|
+
for member in self.sub_members.values():
|
|
249
|
+
V = member.max_shear(Direction, name)
|
|
250
|
+
if Vmax is None or V > Vmax:
|
|
251
|
+
Vmax = V
|
|
252
|
+
governing_combo = name
|
|
253
|
+
|
|
254
|
+
if Vmax is None:
|
|
255
|
+
Vmax = 0
|
|
256
|
+
if isinstance(combo_tags, list):
|
|
257
|
+
return (Vmax, governing_combo)
|
|
237
258
|
return Vmax
|
|
238
259
|
|
|
239
|
-
def min_shear(self, Direction: Literal['Fy', 'Fz'],
|
|
260
|
+
def min_shear(self, Direction: Literal['Fy', 'Fz'], combo_tags: Union[str, List[str]] = 'Combo 1') -> Union[float, tuple[float, str]]:
|
|
240
261
|
"""
|
|
241
|
-
Returns the minimum shear in the member for the given direction
|
|
262
|
+
Returns the minimum shear in the member for the given direction.
|
|
242
263
|
|
|
243
264
|
Parameters
|
|
244
265
|
----------
|
|
@@ -246,15 +267,36 @@ class PhysMember(Member3D):
|
|
|
246
267
|
The direction in which to find the minimum shear. Must be one of the following:
|
|
247
268
|
'Fy' = Shear acting on the local y-axis
|
|
248
269
|
'Fz' = Shear acting on the local z-axis
|
|
249
|
-
|
|
250
|
-
|
|
270
|
+
combo_tags : str or list of str
|
|
271
|
+
A single load combination name, or a list of combo tags.
|
|
272
|
+
|
|
273
|
+
Returns
|
|
274
|
+
-------
|
|
275
|
+
float or tuple of (float, str)
|
|
276
|
+
If a single combo name is provided, returns the minimum shear value.
|
|
277
|
+
If a list of tags is provided, returns a tuple of the minimum shear
|
|
278
|
+
value and the name of the governing load combination.
|
|
251
279
|
"""
|
|
252
280
|
|
|
281
|
+
if isinstance(combo_tags, str):
|
|
282
|
+
combo_names = [combo_tags]
|
|
283
|
+
else:
|
|
284
|
+
combo_names = [name for name, combo in self.model.load_combos.items()
|
|
285
|
+
if any(tag in combo.combo_tags for tag in combo_tags)]
|
|
286
|
+
|
|
253
287
|
Vmin = None
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
288
|
+
governing_combo = None
|
|
289
|
+
for name in combo_names:
|
|
290
|
+
for member in self.sub_members.values():
|
|
291
|
+
V = member.min_shear(Direction, name)
|
|
292
|
+
if Vmin is None or V < Vmin:
|
|
293
|
+
Vmin = V
|
|
294
|
+
governing_combo = name
|
|
295
|
+
|
|
296
|
+
if Vmin is None:
|
|
297
|
+
Vmin = 0
|
|
298
|
+
if isinstance(combo_tags, list):
|
|
299
|
+
return (Vmin, governing_combo)
|
|
258
300
|
return Vmin
|
|
259
301
|
|
|
260
302
|
def plot_shear(self, Direction: Literal['Fy', 'Fz'], combo_name: Union[str, List[str]] = 'Combo 1', n_points: int = 20) -> None:
|
|
@@ -405,46 +447,88 @@ class PhysMember(Member3D):
|
|
|
405
447
|
member, x_mod = self.find_member(x)
|
|
406
448
|
return member.moment(Direction, x_mod, combo_name)
|
|
407
449
|
|
|
408
|
-
def max_moment(self, Direction: Literal['My', 'Mz'],
|
|
450
|
+
def max_moment(self, Direction: Literal['My', 'Mz'], combo_tags: Union[str, List[str]] = 'Combo 1') -> Union[float, tuple[float, str]]:
|
|
409
451
|
"""
|
|
410
452
|
Returns the maximum moment in the member for the given direction.
|
|
411
|
-
|
|
453
|
+
|
|
412
454
|
Parameters
|
|
413
455
|
----------
|
|
414
456
|
Direction : string
|
|
415
457
|
The direction in which to find the maximum moment. Must be one of the following:
|
|
416
458
|
'My' = Moment about the local y-axis.
|
|
417
459
|
'Mz' = Moment about the local z-axis.
|
|
418
|
-
|
|
419
|
-
|
|
460
|
+
combo_tags : str or list of str
|
|
461
|
+
A single load combination name, or a list of combo tags.
|
|
462
|
+
|
|
463
|
+
Returns
|
|
464
|
+
-------
|
|
465
|
+
float or tuple of (float, str)
|
|
466
|
+
If a single combo name is provided, returns the maximum moment value.
|
|
467
|
+
If a list of tags is provided, returns a tuple of the maximum moment
|
|
468
|
+
value and the name of the governing load combination.
|
|
420
469
|
"""
|
|
421
470
|
|
|
471
|
+
if isinstance(combo_tags, str):
|
|
472
|
+
combo_names = [combo_tags]
|
|
473
|
+
else:
|
|
474
|
+
combo_names = [name for name, combo in self.model.load_combos.items()
|
|
475
|
+
if any(tag in combo.combo_tags for tag in combo_tags)]
|
|
476
|
+
|
|
422
477
|
Mmax = None
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
478
|
+
governing_combo = None
|
|
479
|
+
for name in combo_names:
|
|
480
|
+
for member in self.sub_members.values():
|
|
481
|
+
M = member.max_moment(Direction, name)
|
|
482
|
+
if Mmax is None or M > Mmax:
|
|
483
|
+
Mmax = M
|
|
484
|
+
governing_combo = name
|
|
485
|
+
|
|
486
|
+
if Mmax is None:
|
|
487
|
+
Mmax = 0
|
|
488
|
+
if isinstance(combo_tags, list):
|
|
489
|
+
return (Mmax, governing_combo)
|
|
427
490
|
return Mmax
|
|
428
491
|
|
|
429
|
-
def min_moment(self, Direction: Literal['My', 'Mz'],
|
|
492
|
+
def min_moment(self, Direction: Literal['My', 'Mz'], combo_tags: Union[str, List[str]] = 'Combo 1') -> Union[float, tuple[float, str]]:
|
|
430
493
|
"""
|
|
431
|
-
Returns the minimum moment in the member for the given direction
|
|
432
|
-
|
|
494
|
+
Returns the minimum moment in the member for the given direction.
|
|
495
|
+
|
|
433
496
|
Parameters
|
|
434
497
|
----------
|
|
435
498
|
Direction : string
|
|
436
499
|
The direction in which to find the minimum moment. Must be one of the following:
|
|
437
500
|
'My' = Moment about the local y-axis.
|
|
438
501
|
'Mz' = Moment about the local z-axis.
|
|
439
|
-
|
|
440
|
-
|
|
502
|
+
combo_tags : str or list of str
|
|
503
|
+
A single load combination name, or a list of combo tags.
|
|
504
|
+
|
|
505
|
+
Returns
|
|
506
|
+
-------
|
|
507
|
+
float or tuple of (float, str)
|
|
508
|
+
If a single combo name is provided, returns the minimum moment value.
|
|
509
|
+
If a list of tags is provided, returns a tuple of the minimum moment
|
|
510
|
+
value and the name of the governing load combination.
|
|
441
511
|
"""
|
|
442
|
-
|
|
512
|
+
|
|
513
|
+
if isinstance(combo_tags, str):
|
|
514
|
+
combo_names = [combo_tags]
|
|
515
|
+
else:
|
|
516
|
+
combo_names = [name for name, combo in self.model.load_combos.items()
|
|
517
|
+
if any(tag in combo.combo_tags for tag in combo_tags)]
|
|
518
|
+
|
|
443
519
|
Mmin = None
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
520
|
+
governing_combo = None
|
|
521
|
+
for name in combo_names:
|
|
522
|
+
for member in self.sub_members.values():
|
|
523
|
+
M = member.min_moment(Direction, name)
|
|
524
|
+
if Mmin is None or M < Mmin:
|
|
525
|
+
Mmin = M
|
|
526
|
+
governing_combo = name
|
|
527
|
+
|
|
528
|
+
if Mmin is None:
|
|
529
|
+
Mmin = 0
|
|
530
|
+
if isinstance(combo_tags, list):
|
|
531
|
+
return (Mmin, governing_combo)
|
|
448
532
|
return Mmin
|
|
449
533
|
|
|
450
534
|
def plot_moment(self, Direction: Literal['My', 'Mz'], combo_name: Union[str, List[str]] = 'Combo 1', n_points: int = 20) -> None:
|
|
@@ -598,30 +682,80 @@ class PhysMember(Member3D):
|
|
|
598
682
|
member, x_mod = self.find_member(x)
|
|
599
683
|
return member.torque(x_mod, combo_name)
|
|
600
684
|
|
|
601
|
-
def max_torque(self,
|
|
602
|
-
|
|
685
|
+
def max_torque(self, combo_tags: Union[str, List[str]] = 'Combo 1') -> Union[float, tuple[float, str]]:
|
|
686
|
+
"""
|
|
687
|
+
Returns the maximum torsional moment in the member.
|
|
688
|
+
|
|
689
|
+
Parameters
|
|
690
|
+
----------
|
|
691
|
+
combo_tags : str or list of str
|
|
692
|
+
A single load combination name, or a list of combo tags.
|
|
693
|
+
|
|
694
|
+
Returns
|
|
695
|
+
-------
|
|
696
|
+
float or tuple of (float, str)
|
|
697
|
+
If a single combo name is provided, returns the maximum torque value.
|
|
698
|
+
If a list of tags is provided, returns a tuple of the maximum torque
|
|
699
|
+
value and the name of the governing load combination.
|
|
700
|
+
"""
|
|
701
|
+
|
|
702
|
+
if isinstance(combo_tags, str):
|
|
703
|
+
combo_names = [combo_tags]
|
|
704
|
+
else:
|
|
705
|
+
combo_names = [name for name, combo in self.model.load_combos.items()
|
|
706
|
+
if any(tag in combo.combo_tags for tag in combo_tags)]
|
|
707
|
+
|
|
603
708
|
Tmax = None
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
709
|
+
governing_combo = None
|
|
710
|
+
for name in combo_names:
|
|
711
|
+
for member in self.sub_members.values():
|
|
712
|
+
T = member.max_torque(name)
|
|
713
|
+
if Tmax is None or T > Tmax:
|
|
714
|
+
Tmax = T
|
|
715
|
+
governing_combo = name
|
|
716
|
+
|
|
717
|
+
if Tmax is None:
|
|
718
|
+
Tmax = 0
|
|
719
|
+
if isinstance(combo_tags, list):
|
|
720
|
+
return (Tmax, governing_combo)
|
|
608
721
|
return Tmax
|
|
609
722
|
|
|
610
|
-
def min_torque(self,
|
|
723
|
+
def min_torque(self, combo_tags: Union[str, List[str]] = 'Combo 1') -> Union[float, tuple[float, str]]:
|
|
611
724
|
"""
|
|
612
725
|
Returns the minimum torsional moment in the member.
|
|
613
726
|
|
|
614
727
|
Parameters
|
|
615
728
|
----------
|
|
616
|
-
|
|
617
|
-
|
|
729
|
+
combo_tags : str or list of str
|
|
730
|
+
A single load combination name, or a list of combo tags.
|
|
731
|
+
|
|
732
|
+
Returns
|
|
733
|
+
-------
|
|
734
|
+
float or tuple of (float, str)
|
|
735
|
+
If a single combo name is provided, returns the minimum torque value.
|
|
736
|
+
If a list of tags is provided, returns a tuple of the minimum torque
|
|
737
|
+
value and the name of the governing load combination.
|
|
618
738
|
"""
|
|
619
739
|
|
|
740
|
+
if isinstance(combo_tags, str):
|
|
741
|
+
combo_names = [combo_tags]
|
|
742
|
+
else:
|
|
743
|
+
combo_names = [name for name, combo in self.model.load_combos.items()
|
|
744
|
+
if any(tag in combo.combo_tags for tag in combo_tags)]
|
|
745
|
+
|
|
620
746
|
Tmin = None
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
747
|
+
governing_combo = None
|
|
748
|
+
for name in combo_names:
|
|
749
|
+
for member in self.sub_members.values():
|
|
750
|
+
T = member.min_torque(name)
|
|
751
|
+
if Tmin is None or T < Tmin:
|
|
752
|
+
Tmin = T
|
|
753
|
+
governing_combo = name
|
|
754
|
+
|
|
755
|
+
if Tmin is None:
|
|
756
|
+
Tmin = 0
|
|
757
|
+
if isinstance(combo_tags, list):
|
|
758
|
+
return (Tmin, governing_combo)
|
|
625
759
|
return Tmin
|
|
626
760
|
|
|
627
761
|
def plot_torque(self, combo_name: Union[str, List[str]] = 'Combo 1', n_points: int = 20) -> None:
|
|
@@ -756,22 +890,80 @@ class PhysMember(Member3D):
|
|
|
756
890
|
member, x_mod = self.find_member(x)
|
|
757
891
|
return member.axial(x_mod, combo_name)
|
|
758
892
|
|
|
759
|
-
def max_axial(self,
|
|
760
|
-
|
|
893
|
+
def max_axial(self, combo_tags: Union[str, List[str]] = 'Combo 1') -> Union[float, tuple[float, str]]:
|
|
894
|
+
"""
|
|
895
|
+
Returns the maximum axial force in the member.
|
|
896
|
+
|
|
897
|
+
Parameters
|
|
898
|
+
----------
|
|
899
|
+
combo_tags : str or list of str
|
|
900
|
+
A single load combination name, or a list of combo tags.
|
|
901
|
+
|
|
902
|
+
Returns
|
|
903
|
+
-------
|
|
904
|
+
float or tuple of (float, str)
|
|
905
|
+
If a single combo name is provided, returns the maximum axial value.
|
|
906
|
+
If a list of tags is provided, returns a tuple of the maximum axial
|
|
907
|
+
value and the name of the governing load combination.
|
|
908
|
+
"""
|
|
909
|
+
|
|
910
|
+
if isinstance(combo_tags, str):
|
|
911
|
+
combo_names = [combo_tags]
|
|
912
|
+
else:
|
|
913
|
+
combo_names = [name for name, combo in self.model.load_combos.items()
|
|
914
|
+
if any(tag in combo.combo_tags for tag in combo_tags)]
|
|
915
|
+
|
|
761
916
|
Pmax = None
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
917
|
+
governing_combo = None
|
|
918
|
+
for name in combo_names:
|
|
919
|
+
for member in self.sub_members.values():
|
|
920
|
+
P = member.max_axial(name)
|
|
921
|
+
if Pmax is None or P > Pmax:
|
|
922
|
+
Pmax = P
|
|
923
|
+
governing_combo = name
|
|
924
|
+
|
|
925
|
+
if Pmax is None:
|
|
926
|
+
Pmax = 0
|
|
927
|
+
if isinstance(combo_tags, list):
|
|
928
|
+
return (Pmax, governing_combo)
|
|
766
929
|
return Pmax
|
|
767
930
|
|
|
768
|
-
def min_axial(self,
|
|
931
|
+
def min_axial(self, combo_tags: Union[str, List[str]] = 'Combo 1') -> Union[float, tuple[float, str]]:
|
|
932
|
+
"""
|
|
933
|
+
Returns the minimum axial force in the member.
|
|
934
|
+
|
|
935
|
+
Parameters
|
|
936
|
+
----------
|
|
937
|
+
combo_tags : str or list of str
|
|
938
|
+
A single load combination name, or a list of combo tags.
|
|
939
|
+
|
|
940
|
+
Returns
|
|
941
|
+
-------
|
|
942
|
+
float or tuple of (float, str)
|
|
943
|
+
If a single combo name is provided, returns the minimum axial value.
|
|
944
|
+
If a list of tags is provided, returns a tuple of the minimum axial
|
|
945
|
+
value and the name of the governing load combination.
|
|
946
|
+
"""
|
|
947
|
+
|
|
948
|
+
if isinstance(combo_tags, str):
|
|
949
|
+
combo_names = [combo_tags]
|
|
950
|
+
else:
|
|
951
|
+
combo_names = [name for name, combo in self.model.load_combos.items()
|
|
952
|
+
if any(tag in combo.combo_tags for tag in combo_tags)]
|
|
769
953
|
|
|
770
954
|
Pmin = None
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
955
|
+
governing_combo = None
|
|
956
|
+
for name in combo_names:
|
|
957
|
+
for member in self.sub_members.values():
|
|
958
|
+
P = member.min_axial(name)
|
|
959
|
+
if Pmin is None or P < Pmin:
|
|
960
|
+
Pmin = P
|
|
961
|
+
governing_combo = name
|
|
962
|
+
|
|
963
|
+
if Pmin is None:
|
|
964
|
+
Pmin = 0
|
|
965
|
+
if isinstance(combo_tags, list):
|
|
966
|
+
return (Pmin, governing_combo)
|
|
775
967
|
return Pmin
|
|
776
968
|
|
|
777
969
|
def plot_axial(self, combo_name: Union[str, List[str]] = 'Combo 1', n_points: int = 20) -> None:
|
|
@@ -910,42 +1102,84 @@ class PhysMember(Member3D):
|
|
|
910
1102
|
member, x_mod = self.find_member(x)
|
|
911
1103
|
return member.deflection(Direction, x_mod, combo_name)
|
|
912
1104
|
|
|
913
|
-
def max_deflection(self, Direction: Literal['dx', 'dy', 'dz'],
|
|
1105
|
+
def max_deflection(self, Direction: Literal['dx', 'dy', 'dz'], combo_tags: Union[str, List[str]] = 'Combo 1') -> Union[float, tuple[float, str]]:
|
|
914
1106
|
"""
|
|
915
1107
|
Returns the maximum deflection in the member.
|
|
916
|
-
|
|
1108
|
+
|
|
917
1109
|
Parameters
|
|
918
1110
|
----------
|
|
919
|
-
Direction : {'dy', 'dz'}
|
|
1111
|
+
Direction : {'dx', 'dy', 'dz'}
|
|
920
1112
|
The direction in which to find the maximum deflection.
|
|
921
|
-
|
|
922
|
-
|
|
1113
|
+
combo_tags : str or list of str
|
|
1114
|
+
A single load combination name, or a list of combo tags.
|
|
1115
|
+
|
|
1116
|
+
Returns
|
|
1117
|
+
-------
|
|
1118
|
+
float or tuple of (float, str)
|
|
1119
|
+
If a single combo name is provided, returns the maximum deflection.
|
|
1120
|
+
If a list of tags is provided, returns a tuple of the maximum
|
|
1121
|
+
deflection and the name of the governing load combination.
|
|
923
1122
|
"""
|
|
924
1123
|
|
|
1124
|
+
if isinstance(combo_tags, str):
|
|
1125
|
+
combo_names = [combo_tags]
|
|
1126
|
+
else:
|
|
1127
|
+
combo_names = [name for name, combo in self.model.load_combos.items()
|
|
1128
|
+
if any(tag in combo.combo_tags for tag in combo_tags)]
|
|
1129
|
+
|
|
925
1130
|
dmax = None
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
1131
|
+
governing_combo = None
|
|
1132
|
+
for name in combo_names:
|
|
1133
|
+
for member in self.sub_members.values():
|
|
1134
|
+
d = member.max_deflection(Direction, name)
|
|
1135
|
+
if dmax is None or d > dmax:
|
|
1136
|
+
dmax = d
|
|
1137
|
+
governing_combo = name
|
|
1138
|
+
|
|
1139
|
+
if dmax is None:
|
|
1140
|
+
dmax = 0
|
|
1141
|
+
if isinstance(combo_tags, list):
|
|
1142
|
+
return (dmax, governing_combo)
|
|
930
1143
|
return dmax
|
|
931
1144
|
|
|
932
|
-
def min_deflection(self, Direction: Literal['dx', 'dy', 'dz'],
|
|
1145
|
+
def min_deflection(self, Direction: Literal['dx', 'dy', 'dz'], combo_tags: Union[str, List[str]] = 'Combo 1') -> Union[float, tuple[float, str]]:
|
|
933
1146
|
"""
|
|
934
1147
|
Returns the minimum deflection in the member.
|
|
935
|
-
|
|
1148
|
+
|
|
936
1149
|
Parameters
|
|
937
1150
|
----------
|
|
938
|
-
Direction : {'dy', 'dz'}
|
|
1151
|
+
Direction : {'dx', 'dy', 'dz'}
|
|
939
1152
|
The direction in which to find the minimum deflection.
|
|
940
|
-
|
|
941
|
-
|
|
1153
|
+
combo_tags : str or list of str
|
|
1154
|
+
A single load combination name, or a list of combo tags.
|
|
1155
|
+
|
|
1156
|
+
Returns
|
|
1157
|
+
-------
|
|
1158
|
+
float or tuple of (float, str)
|
|
1159
|
+
If a single combo name is provided, returns the minimum deflection.
|
|
1160
|
+
If a list of tags is provided, returns a tuple of the minimum
|
|
1161
|
+
deflection and the name of the governing load combination.
|
|
942
1162
|
"""
|
|
943
1163
|
|
|
1164
|
+
if isinstance(combo_tags, str):
|
|
1165
|
+
combo_names = [combo_tags]
|
|
1166
|
+
else:
|
|
1167
|
+
combo_names = [name for name, combo in self.model.load_combos.items()
|
|
1168
|
+
if any(tag in combo.combo_tags for tag in combo_tags)]
|
|
1169
|
+
|
|
944
1170
|
dmin = None
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
1171
|
+
governing_combo = None
|
|
1172
|
+
for name in combo_names:
|
|
1173
|
+
for member in self.sub_members.values():
|
|
1174
|
+
d = member.min_deflection(Direction, name)
|
|
1175
|
+
if dmin is None or d < dmin:
|
|
1176
|
+
dmin = d
|
|
1177
|
+
governing_combo = name
|
|
1178
|
+
|
|
1179
|
+
if dmin is None:
|
|
1180
|
+
dmin = 0
|
|
1181
|
+
if isinstance(combo_tags, list):
|
|
1182
|
+
return (dmin, governing_combo)
|
|
949
1183
|
return dmin
|
|
950
1184
|
|
|
951
1185
|
def rel_deflection(self, Direction: Literal['dx', 'dy', 'dz'], x: float, combo_name: str = 'Combo 1') -> float:
|
|
@@ -1599,12 +1599,9 @@ def _PrepContour(model, stress_type='Mx', combo_name='Combo 1'):
|
|
|
1599
1599
|
|
|
1600
1600
|
# Determine which stress result has been requested by the user
|
|
1601
1601
|
if stress_type == 'dz':
|
|
1602
|
-
#
|
|
1603
|
-
#
|
|
1604
|
-
|
|
1605
|
-
i, j, m, n = element.d(combo_name)[[2, 8, 14, 20], :]
|
|
1606
|
-
else:
|
|
1607
|
-
i, j, m, n = element.d(combo_name)[[14, 20, 2, 8], :]
|
|
1602
|
+
# Both rectangular and quadrilateral elements store local displacements in the
|
|
1603
|
+
# order (i, j, m, n) in their d() vectors. Local DZ is at indices 2, 8, 14, 20.
|
|
1604
|
+
i, j, m, n = element.d(combo_name)[[2, 8, 14, 20], :]
|
|
1608
1605
|
element.i_node.contour.append(i)
|
|
1609
1606
|
element.j_node.contour.append(j)
|
|
1610
1607
|
element.m_node.contour.append(m)
|
|
@@ -68,9 +68,12 @@ Here's a list of projects that use Pynite:
|
|
|
68
68
|
* Phaenotyp (https://github.com/bewegende-Architektur/Phaenotyp) (https://youtu.be/shloSw9HjVI)
|
|
69
69
|
|
|
70
70
|
# What's New?
|
|
71
|
+
2.4.0
|
|
72
|
+
* Member `max` and `min` methods now return governing load combination along with the member max/min forces.
|
|
73
|
+
* Bug fix: Quadrilateral element displacements had corners swapped during VTK visualization. This was a relic from the old MITC4 formulation that has been corrected.
|
|
74
|
+
|
|
71
75
|
v2.3.0
|
|
72
76
|
* Added enveloping to member diagrams. Set `combo_name` to a list of combo tags and the member diagram will show an envelope of all the combos that have any of those tags.
|
|
73
|
-
* Bug fix: Quadrilateral element displacements had corners swapped during VTK visualization. This was a relic from the old MITC4 formulation that has been corrected.
|
|
74
77
|
* Bug fix: Added shear wall and mat foundation load cases to `FEModel3D.load_cases()`. The list of load cases was sometimes incomplete if these meshes had not yet been generated.
|
|
75
78
|
* Added bending moment end releases to visualizations.
|
|
76
79
|
* Bug fix for shear walls with flanges having an origin with their origin at Y != 0.
|
|
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
|
|
|
5
5
|
|
|
6
6
|
setuptools.setup(
|
|
7
7
|
name="PyNiteFEA",
|
|
8
|
-
version="2.
|
|
8
|
+
version="2.4.0",
|
|
9
9
|
author="D. Craig Brinck, PE, SE",
|
|
10
10
|
author_email="Building.Code@outlook.com",
|
|
11
11
|
description="A simple elastic 3D structural finite element library for Python.",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|