diff --git a/PyNite/Analysis.py b/PyNite/Analysis.py index 3c50e70..e675f8c 100644 --- a/PyNite/Analysis.py +++ b/PyNite/Analysis.py @@ -527,20 +527,35 @@ def _check_TC_convergence(model, combo_name="Combo 1", log=True, spring_toleranc # Only run the tension/compression only check if the member is still active if phys_member.active[combo_name] == True: - # Check if tension-only conditions exist + + # Check if a tension-only conditions exist if ( phys_member.tension_only == True and phys_member.max_axial(combo_name) > member_tolerance ): + # Deactivate the physical member phys_member.active[combo_name] = False + + # Deactivate all the sub-members + for sub_member in phys_member.sub_members.values(): + sub_member.active[combo_name] = False + + # Flag the analysis as not converged convergence = False - # Check if compression-only conditions exist + # Check if a compression-only conditions exist elif ( phys_member.comp_only == True and phys_member.min_axial(combo_name) < -member_tolerance ): + # Deactivate the physical member phys_member.active[combo_name] = False + + # Deactivate all the sub-members + for sub_member in phys_member.sub_members.values(): + sub_member.active[combo_name] = False + + # Flag the analysis as not converged convergence = False # Reset the sub-member's flag to unsolved. This will allow it to resolve for the same load combination after subsequent iterations have made further changes. diff --git a/PyNite/FEModel3D.py b/PyNite/FEModel3D.py index 4918d5b..3fae33c 100644 --- a/PyNite/FEModel3D.py +++ b/PyNite/FEModel3D.py @@ -2009,6 +2009,7 @@ def analyze(self, log=False, check_stability=True, check_statics=False, max_iter convergence = Analysis._check_TC_convergence(self, combo.name, log=log, spring_tolerance=spring_tolerance, member_tolerance=member_tolerance) if convergence == False: + if log: print('- Tension/compression-only analysis did not converge. Adjusting stiffness matrix and reanalyzing.') else: if log: print('- Tension/compression-only analysis converged after ' + str(iter_count) + ' iteration(s)') @@ -2027,7 +2028,7 @@ def analyze(self, log=False, check_stability=True, check_statics=False, max_iter # Check statics if requested if check_statics == True: Analysis._check_statics(self, combo_tags) - + # Flag the model as solved self.solution = 'Linear TC' diff --git a/PyNite/Member3D.py b/PyNite/Member3D.py index 3fe257d..ef7f2d7 100644 --- a/PyNite/Member3D.py +++ b/PyNite/Member3D.py @@ -705,7 +705,7 @@ def shear(self, Direction, x, combo_name='Combo 1'): """ # Only calculate results if the member is currently active - if self.active: + if self.active[combo_name]: # Segment the member if necessary if self._solved_combo is None or combo_name != self._solved_combo.name: @@ -757,7 +757,7 @@ def max_shear(self, Direction, combo_name='Combo 1'): """ # Only calculate results if the member is currently active - if self.active: + if self.active[combo_name]: # Segment the member if necessary if self._solved_combo is None or combo_name != self._solved_combo.name: @@ -806,7 +806,7 @@ def min_shear(self, Direction, combo_name='Combo 1'): """ # Only calculate results if the member is currently active - if self.active: + if self.active[combo_name]: # Segment the member if necessary if self._solved_combo is None or combo_name != self._solved_combo.name: @@ -938,7 +938,7 @@ def moment(self, Direction, x, combo_name='Combo 1'): """ # Only calculate results if the member is currently active - if self.active: + if self.active[combo_name]: # Segment the member if necessary if self._solved_combo is None or combo_name != self._solved_combo.name: @@ -1002,7 +1002,7 @@ def max_moment(self, Direction, combo_name='Combo 1'): """ # Only calculate results if the member is currently active - if self.active: + if self.active[combo_name]: # Determine if a P-Delta analysis has been run if self.model.solution == 'P-Delta' or self.model.solution == 'Pushover': @@ -1059,7 +1059,7 @@ def min_moment(self, Direction, combo_name='Combo 1'): """ # Only calculate results if the member is currently active - if self.active: + if self.active[combo_name]: # Segment the member if necessary if self._solved_combo is None or combo_name != self._solved_combo.name: @@ -1204,7 +1204,7 @@ def torque(self, x, combo_name='Combo 1'): """ # Only calculate results if the member is currently active - if self.active: + if self.active[combo_name]: # Segment the member if necessary if self._solved_combo is None or combo_name != self._solved_combo.name: @@ -1236,7 +1236,7 @@ def max_torque(self, combo_name='Combo 1'): """ # Only calculate results if the member is currently active - if self.active: + if self.active[combo_name]: # Segment the member if necessary if self._solved_combo is None or combo_name != self._solved_combo.name: @@ -1269,7 +1269,7 @@ def min_torque(self, combo_name='Combo 1'): """ # Only calculate results if the member is currently active - if self.active: + if self.active[combo_name]: # Segment the member if necessary if self._solved_combo is None or combo_name != self._solved_combo.name: @@ -1368,7 +1368,7 @@ def axial(self, x, combo_name='Combo 1'): """ # Only calculate results if the member is currently active - if self.active: + if self.active[combo_name]: # Segment the member if necessary if self._solved_combo is None or combo_name != self._solved_combo.name: @@ -1399,7 +1399,7 @@ def max_axial(self, combo_name='Combo 1'): """ # Only calculate results if the member is currently active - if self.active: + if self.active[combo_name]: # Segment the member if necessary if self._solved_combo is None or combo_name != self._solved_combo.name: @@ -1431,7 +1431,7 @@ def min_axial(self, combo_name='Combo 1'): """ # Only calculate results if the member is currently active - if self.active: + if self.active[combo_name]: # Segment the member if necessary if self._solved_combo is None or combo_name != self._solved_combo.name: @@ -1534,7 +1534,7 @@ def deflection(self, Direction, x, combo_name='Combo 1'): """ # Only calculate results if the member is currently active - if self.active: + if self.active[combo_name]: # Segment the member if necessary if self._solved_combo is None or combo_name != self._solved_combo.name: @@ -1604,7 +1604,7 @@ def max_deflection(self, Direction, combo_name='Combo 1'): """ # Only calculate results if the member is currently active - if self.active: + if self.active[combo_name]: # Segment the member if necessary if self._solved_combo is None or combo_name != self._solved_combo.name: @@ -1640,7 +1640,7 @@ def min_deflection(self, Direction, combo_name='Combo 1'): """ # Only calculate results if the member is currently active - if self.active: + if self.active[combo_name]: # Segment the member if necessary if self._solved_combo is None or combo_name != self._solved_combo.name: @@ -1775,7 +1775,7 @@ def rel_deflection(self, Direction, x, combo_name='Combo 1'): """ # Only calculate results if the member is currently active - if self.active: + if self.active[combo_name]: # Segment the member if necessary if self._solved_combo is None or combo_name != self._solved_combo.name: diff --git a/PyNite/PhysMember.py b/PyNite/PhysMember.py index ebd2217..04e3f41 100644 --- a/PyNite/PhysMember.py +++ b/PyNite/PhysMember.py @@ -16,6 +16,7 @@ def __init__(self, name, i_node, j_node, material_name, model, Iy, Iz, J, A, aux tension_only=False, comp_only=False, section_name=None): super().__init__(name, i_node, j_node, material_name, model, Iy, Iz, J, A, aux_node, tension_only, comp_only, section_name) + self.sub_members = {} def descritize(self):