@@ -632,7 +632,9 @@ def calculate_service_section_actions(
632
632
self ,
633
633
d_n : float ,
634
634
kappa : float ,
635
- moment_curvature : res .MomentCurvatureResults = res .MomentCurvatureResults (),
635
+ moment_curvature : res .MomentCurvatureResults = res .MomentCurvatureResults (
636
+ theta = 0
637
+ ),
636
638
) -> res .MomentCurvatureResults :
637
639
"""Given a neutral axis depth `d_n` and curvature `kappa`, calculates the
638
640
resultant axial force and bending moment.
@@ -782,7 +784,7 @@ def ultimate_bending_capacity(
782
784
b = d_t # neutral axis at extreme tensile fibre
783
785
784
786
# initialise ultimate bending results
785
- ultimate_results = res .UltimateBendingResults ()
787
+ ultimate_results = res .UltimateBendingResults (theta = theta )
786
788
787
789
# find neutral axis that gives convergence of the axial force
788
790
(d_n , r ) = brentq (
@@ -805,8 +807,7 @@ def ultimate_normal_force_convergence(
805
807
ultimate_results : results .UltimateBendingResults ,
806
808
) -> float :
807
809
"""Given a neutral axis depth `d_n` and neutral axis angle `theta`, calculates
808
- the difference between the target net axial force `n` and the axial force
809
- given `d_n` & `theta`.
810
+ the difference between the target net axial force `n` and the axial force.
810
811
811
812
:param float d_n: Depth of the neutral axis from the extreme compression fibre
812
813
:param float n: Net axial force
@@ -829,7 +830,9 @@ def ultimate_normal_force_convergence(
829
830
def calculate_ultimate_section_actions (
830
831
self ,
831
832
d_n : float ,
832
- ultimate_results : results .UltimateBendingResults ,
833
+ ultimate_results : res .UltimateBendingResults = res .UltimateBendingResults (
834
+ theta = 0
835
+ ),
833
836
) -> results .UltimateBendingResults :
834
837
"""Given a neutral axis depth `d_n` and neutral axis angle `theta`, calculates
835
838
the resultant bending moments `mx`, `my`, `mv` and the net axial force `n`.
@@ -962,13 +965,16 @@ def calculate_ultimate_section_actions(
962
965
def moment_interaction_diagram (
963
966
self ,
964
967
theta : float = 0 ,
968
+ m_neg : bool = False ,
965
969
n_points : int = 24 ,
966
970
) -> res .MomentInteractionResults :
967
971
"""Generates a moment interaction diagram given a neutral axis angle `theta`
968
972
and `n_points` calculation points between the decompression case and the pure
969
973
bending case.
970
974
971
975
:param float theta: Angle the neutral axis makes with the horizontal axis
976
+ :param bool m_neg: If set to true, also calculates the moment interaction for
977
+ theta = theta + pi, i.e. positive and negative bending
972
978
:param int n_points: Number of calculation points between the decompression
973
979
case and the pure bending case.
974
980
@@ -994,9 +1000,14 @@ def moment_interaction_diagram(
994
1000
995
1001
# create progress bar
996
1002
with utils .create_known_progress () as progress :
1003
+ progress_length = n_points
1004
+
1005
+ if m_neg :
1006
+ progress_length *= 2
1007
+
997
1008
task = progress .add_task (
998
1009
description = "[red]Generating M-N diagram" ,
999
- total = n_points ,
1010
+ total = progress_length ,
1000
1011
)
1001
1012
1002
1013
for d_n in d_n_list :
@@ -1007,16 +1018,100 @@ def moment_interaction_diagram(
1007
1018
mi_results .m .append (ultimate_results .mv )
1008
1019
progress .update (task , advance = 1 )
1009
1020
1021
+ if not m_neg :
1022
+ progress .update (
1023
+ task ,
1024
+ description = "[bold green]:white_check_mark: M-N diagram generated" ,
1025
+ )
1026
+
1027
+ # add tensile load
1028
+ mi_results .n .append (self .gross_properties .tensile_load )
1029
+ mi_results .m .append (0 )
1030
+
1031
+ # if calculating negative bending
1032
+ if m_neg :
1033
+ theta += np .pi
1034
+ # compute extreme tensile fibre
1035
+ _ , d_t = utils .calculate_extreme_fibre (
1036
+ points = self .geometry .points , theta = theta
1037
+ )
1038
+
1039
+ # compute neutral axis depth for pure bending case
1040
+ ultimate_results = self .ultimate_bending_capacity (theta = theta , n = 0 )
1041
+
1042
+ # generate list of neutral axes
1043
+ d_n_list = np .linspace (
1044
+ start = d_t , stop = ultimate_results .d_n , num = n_points
1045
+ )
1046
+
1047
+ for d_n in reversed (d_n_list ):
1048
+ ultimate_results = self .calculate_ultimate_section_actions (
1049
+ d_n = d_n , ultimate_results = ultimate_results
1050
+ )
1051
+ mi_results .n .append (ultimate_results .n )
1052
+ mi_results .m .append (- ultimate_results .mv )
1053
+ progress .update (task , advance = 1 )
1054
+
1055
+ progress .update (
1056
+ task ,
1057
+ description = "[bold green]:white_check_mark: M-N diagram generated" ,
1058
+ )
1059
+
1060
+ # add squash load
1061
+ mi_results .n .append (self .gross_properties .squash_load )
1062
+ mi_results .m .append (0 )
1063
+
1064
+ return mi_results
1065
+
1066
+ def biaxial_bending_diagram (
1067
+ self ,
1068
+ n : float = 0 ,
1069
+ n_points : int = 48 ,
1070
+ ) -> res .BiaxialBendingResults :
1071
+ """Generates a biaxial bending diagram given a net axial force `n` and
1072
+ `n_points` calculation points.
1073
+
1074
+ :param float n: Net axial force
1075
+ :param int n_points: Number of calculation points between the decompression
1076
+ case and the pure bending case.
1077
+
1078
+ :return: Biaxial bending results
1079
+ :rtype: :class:`~concreteproperties.results.BiaxialBendingResults`
1080
+ """
1081
+
1082
+ # initialise results
1083
+ bb_results = res .BiaxialBendingResults (n = n )
1084
+
1085
+ # calculate d_theta
1086
+ d_theta = 2 * np .pi / n_points
1087
+
1088
+ # generate list of thetas
1089
+ theta_list = np .linspace (start = 0 , stop = 2 * np .pi - d_theta , num = n_points )
1090
+
1091
+ # create progress bar
1092
+ with utils .create_known_progress () as progress :
1093
+ task = progress .add_task (
1094
+ description = "[red]Generating biaxial bending diagram" ,
1095
+ total = n_points ,
1096
+ )
1097
+
1098
+ # loop through thetas
1099
+ for theta in theta_list :
1100
+ ultimate_results = self .ultimate_bending_capacity (theta = theta , n = n )
1101
+ bb_results .mx .append (ultimate_results .mx )
1102
+ bb_results .my .append (ultimate_results .my )
1103
+ progress .update (task , advance = 1 )
1104
+
1105
+ # add first result to end of list top
1106
+ bb_results .mx .append (bb_results .mx [0 ])
1107
+ bb_results .my .append (bb_results .my [0 ])
1108
+
1010
1109
progress .update (
1011
1110
task ,
1012
- description = "[bold green]:white_check_mark: M-N diagram generated" ,
1111
+ description = "[bold green]:white_check_mark: Biaxial bending diagram generated" ,
1013
1112
)
1014
1113
1015
- # add tensile load
1016
- mi_results .n .append (self .gross_properties .tensile_load )
1017
- mi_results .m .append (0 )
1018
-
1019
- return mi_results
1114
+ return bb_results
1020
1115
1021
1116
def get_c_local (
1022
1117
self ,
0 commit comments