diff --git a/CHANGELOG.md b/CHANGELOG.md index c2aecd8..16179ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,11 +9,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +* Updated TNA_Loads and TNA_analysis + ### Changed ### Removed - ## [0.2.3] 2025-09-09 ### Added diff --git a/commands/TNA_analysis.py b/commands/TNA_analysis.py index 1cb8c0f..e7896ec 100644 --- a/commands/TNA_analysis.py +++ b/commands/TNA_analysis.py @@ -2,8 +2,6 @@ # venv: brg-csd # r: compas_masonry>=0.2.3 -import ast - import numpy as np import rhinoscriptsyntax as rs # type: ignore @@ -34,6 +32,11 @@ def RunCommand(): formobject.redraw() + sum_loads = sum(formobject.diagram.vertices_attribute("pz")) + if abs(sum_loads) < 0.001: + feedback.warn("There are no loads applied to the model. Please assign loads.") + return + # ============================================================================= # Create an analysis # ============================================================================= @@ -67,10 +70,11 @@ def RunCommand(): index_vertex = formobject.diagram.index_vertex() while True: - formobject.show_vertices = list(formobject.diagram.vertices()) # type: ignore - vertices = formobject.select_vertices() + formobject.show_vertices = list(formobject.vertices()) # type: ignore formobject.redraw() + vertices = formobject.select_vertices() + if not vertices: break @@ -100,30 +104,36 @@ def RunCommand(): while True: formobject.show_vertices = supports - vertices = formobject.select_vertices() formobject.redraw() + vertices = formobject.select_vertices() + if not vertices: break - displ = rs.GetString(message="Vector to displace selected supports", defaultString="[-1, -1, 0]") - - if not displ: - break - - displ_list = ast.literal_eval(displ) - if len(displ_list) != 3: - print("provide a 3x1 vector as shown as the example") - break + ux = rs.GetReal("Define the Support displacement [Ux, Uy, Uz]. Enter Ux", -1) + if not ux: + ux = 0.0 + uy = rs.GetReal("Define the Support displacement [Ux, Uy, Uz]. Enter Uy", -1) + if not uy: + uy = 0.0 + uz = rs.GetReal("Define the Support displacement [Ux, Uy, Uz]. Enter Uz", 0) + if not uz: + uz = 0.0 + displ_list = [ux, uy, uz] for vertex in vertices: displacement_array[supports.index(vertex)] = np.array(displ_list) + print("Applied Vector {0} to support {1}".format(displ_list, vertex)) # Here we should add a vector to the Scene showing the displacement that we are maximizing. add_vector = rs.GetString(message="Define additional displacement vectors?", strings=["Yes", "No"]) rs.UnselectAllObjects() + if not add_vector: + return + if add_vector == "Yes": pass else: @@ -138,11 +148,30 @@ def RunCommand(): raise NotImplementedError analysis.optimiser.settings["printout"] = True # need to be true so people see the fopt. - analysis.apply_selfweight() - analysis.apply_envelope() + # analysis.apply_selfweight() # This needs to be removed if loads were applied previously + # analysis.apply_envelope() # This is also not necessary if we included it before analysis.set_up_optimiser() analysis.run() + # ============================================================================= + # Post Solver Messages + # ============================================================================= + + fopt = analysis.optimiser.fopt + + if objective == "MaximumLoad": + print("Maximum Load Multipled to the loads assigned: {0:.3f}".format(fopt)) + elif objective == "MinimumThrust" or objective == "MaximumThrust": + print("Optimal Horizontal Thrust Calculated: {0:.3f}".format(fopt)) + elif objective == "MinimumThickness": + print("Minimum Thickness Calculated: {0:.3f}".format(fopt)) + elif objective == "SupportDisplacement": + print("Complementary Energy to Assigned Displacements: {0:.3f}".format(fopt)) + elif objective == "Bestfit": + print("Optimal Squared vertical distance to middle surface: {0:.3f}".format(fopt)) + else: + pass + # ============================================================================= # Update scene # ============================================================================= diff --git a/commands/TNA_loads.py b/commands/TNA_loads.py index 871d74f..efcd899 100644 --- a/commands/TNA_loads.py +++ b/commands/TNA_loads.py @@ -30,12 +30,12 @@ def RunCommand(): return # ============================================================================= - # Update the supports + # Update the Loads # ============================================================================= rs.UnselectAllObjects() - options = ["Add", "Clear All"] + options = ["Add", "ClearAll"] option = rs.GetString("Add or Remove Loads in the Model", strings=options) if not option: return @@ -46,7 +46,14 @@ def RunCommand(): return if option == "Selfweight": - envelope.apply_selfweight_to_formdiagram(formdiagram) + option = rs.GetString("Normalize loads to Envelope SWT?", defaultString="Yes", strings=["Yes", "No"]) + if not option: + return + elif option == "Yes": + normalize = True + else: + normalize = False + envelope.apply_selfweight_to_formdiagram(formdiagram, normalize=normalize) elif option == "External": formobject.show_vertices = list(formobject.vertices()) # type: ignore @@ -61,9 +68,11 @@ def RunCommand(): for key in selected: pz = formdiagram.vertex_attribute(key, "pz") or 0 + print("Load at vertex {0} updated from {1:.2f} to {2:.2f}".format(key, pz, pz + load)) formdiagram.vertex_attribute(key, "pz", pz + load) - elif option == "Clear All": + elif option == "ClearAll": + print("Cleared Loads in the Model.") formobject.mesh.vertices_attribute(name="pz", value=0) else: