From 969089b28ae7054b78a457ade8e9c2cfb5f8c584 Mon Sep 17 00:00:00 2001 From: Ricardo Maia Avelino Date: Tue, 9 Sep 2025 12:01:43 +0200 Subject: [PATCH 1/6] fix loads --- commands/TNA_loads.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/commands/TNA_loads.py b/commands/TNA_loads.py index 3d34160..6dcc900 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: From 2fa7ab91b806f745df2796bb0518335baa19b3ce Mon Sep 17 00:00:00 2001 From: Ricardo Maia Avelino Date: Tue, 9 Sep 2025 12:02:26 +0200 Subject: [PATCH 2/6] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d880ca3..d59e803 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +* Added and reviewed TNA_Loads * Added MeshEnvelope options to TNA_Envelope ### Changed From dd17fc855eb227bbdb6a600252c7d113df5c5d0e Mon Sep 17 00:00:00 2001 From: Ricardo Maia Avelino Date: Tue, 9 Sep 2025 12:54:41 +0200 Subject: [PATCH 3/6] Update TNA_analysis --- commands/TNA_analysis.py | 54 +++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/commands/TNA_analysis.py b/commands/TNA_analysis.py index ba99b0c..8d98771 100644 --- a/commands/TNA_analysis.py +++ b/commands/TNA_analysis.py @@ -1,8 +1,6 @@ #! python3 # venv: brg-csd -# r: compas_masonry >=0.2.0 - -import ast +# r: compas_masonry 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,24 +104,21 @@ def RunCommand(): while True: formobject.show_vertices = supports - vertices = formobject.select_vertices() formobject.redraw() - if not vertices: - break - - displ = rs.GetString(message="Vector to displace selected supports", defaultString="[-1, -1, 0]") + vertices = formobject.select_vertices() - if not displ: + if not vertices: 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) + uy = rs.GetReal("Define the Support displacement [Ux, Uy, Uz]. Enter Uy", -1) + uz = rs.GetReal("Define the Support displacement [Ux, Uy, Uz]. Enter Uz", 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. @@ -138,11 +139,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 # ============================================================================= From 22f9feb1a3ce87f904a4f6b820a546e360318356 Mon Sep 17 00:00:00 2001 From: Ricardo Maia Avelino Date: Tue, 9 Sep 2025 13:00:21 +0200 Subject: [PATCH 4/6] Add exit mode for support displ --- commands/TNA_analysis.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/commands/TNA_analysis.py b/commands/TNA_analysis.py index 8d98771..f6db6a7 100644 --- a/commands/TNA_analysis.py +++ b/commands/TNA_analysis.py @@ -2,6 +2,8 @@ # venv: brg-csd # r: compas_masonry +import ast + import numpy as np import rhinoscriptsyntax as rs # type: ignore @@ -112,8 +114,14 @@ def RunCommand(): 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: @@ -125,6 +133,9 @@ def RunCommand(): 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: @@ -151,15 +162,15 @@ def RunCommand(): fopt = analysis.optimiser.fopt if objective == "MaximumLoad": - print("Maximum Load Multipled to the loads assigned: {0:.3f}".format(fopt)) + 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)) + print('Optimal Horizontal Thrust Calculated: {0:.3f}'.format(fopt)) elif objective == "MinimumThickness": - print("Minimum Thickness Calculated: {0:.3f}".format(fopt)) + print('Minimum Thickness Calculated: {0:.3f}'.format(fopt)) elif objective == "SupportDisplacement": - print("Complementary Energy to Assigned Displacements: {0:.3f}".format(fopt)) + 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)) + print('Optimal Squared vertical distance to middle surface: {0:.3f}'.format(fopt)) else: pass From 7748f5bb0f824ec6836b37723f4bd4288ab1fc64 Mon Sep 17 00:00:00 2001 From: Ricardo Maia Avelino Date: Tue, 9 Sep 2025 13:03:06 +0200 Subject: [PATCH 5/6] conflict 1 --- commands/TNA_analysis.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/commands/TNA_analysis.py b/commands/TNA_analysis.py index f6db6a7..e7896ec 100644 --- a/commands/TNA_analysis.py +++ b/commands/TNA_analysis.py @@ -1,8 +1,6 @@ #! python3 # venv: brg-csd -# r: compas_masonry - -import ast +# r: compas_masonry>=0.2.3 import numpy as np import rhinoscriptsyntax as rs # type: ignore @@ -162,15 +160,15 @@ def RunCommand(): fopt = analysis.optimiser.fopt if objective == "MaximumLoad": - print('Maximum Load Multipled to the loads assigned: {0:.3f}'.format(fopt)) + 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)) + print("Optimal Horizontal Thrust Calculated: {0:.3f}".format(fopt)) elif objective == "MinimumThickness": - print('Minimum Thickness Calculated: {0:.3f}'.format(fopt)) + print("Minimum Thickness Calculated: {0:.3f}".format(fopt)) elif objective == "SupportDisplacement": - print('Complementary Energy to Assigned Displacements: {0:.3f}'.format(fopt)) + 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)) + print("Optimal Squared vertical distance to middle surface: {0:.3f}".format(fopt)) else: pass From 79170fab9995ffe097721f6308f76858dde36ac3 Mon Sep 17 00:00:00 2001 From: Ricardo Maia Avelino Date: Tue, 9 Sep 2025 13:06:25 +0200 Subject: [PATCH 6/6] proper changelog --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d880ca3..16179ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,16 @@ 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 + * Added MeshEnvelope options to TNA_Envelope ### Changed