diff --git a/commands/TNA_analysis.py b/commands/TNA_analysis.py index e225a5d..81d5205 100644 --- a/commands/TNA_analysis.py +++ b/commands/TNA_analysis.py @@ -3,6 +3,9 @@ # r: compas_masonry import rhinoscriptsyntax as rs # type: ignore +import ast +from numpy import zeros +from numpy import array from compas_masonry.scene import RhinoFormDiagramObject from compas_masonry.session import MasonrySession as Session @@ -18,13 +21,19 @@ def RunCommand(): envelope = session["envelope"] if not formdiagram: - feedback.warn("There is no FormDiagram. Please create one first.") + feedback.warn("There is no FormDiagram") return if not envelope: - feedback.warn("There is no Envelope. Please create one first.") + feedback.warn("There is no Envelope") return + formobject: RhinoFormDiagramObject = session.scene.find_by_itemtype(FormDiagram) # type: ignore + if not formobject: + session.scene.add(formdiagram, name="FormDiagram", layer="Masonry::TNA::FormDiagram") # type: ignore + + formobject.redraw() + # ============================================================================= # Create an analysis # ============================================================================= @@ -36,6 +45,7 @@ def RunCommand(): "MinimumThickness", "MaximumThrust", "MaximumLoad", + "SupportDisplacement", "Bestfit", ], ) @@ -52,7 +62,73 @@ def RunCommand(): analysis = Analysis.create_maxthrust_analysis(formdiagram, envelope) elif objective == "MaximumLoad": - analysis = Analysis.create_max_load_analysis(formdiagram, envelope) + n = formobject.diagram.number_of_vertices() + load_direction = zeros((n, 1)) + index_vertex = formobject.diagram.index_vertex() + + while True: + formobject.show_vertices = list(formobject.diagram.vertices()) + vertices = formobject.select_vertices() + formobject.redraw() + + if not vertices: + break + + force = rs.GetReal(message="Load to assign to selected vertices (negative downwards):", number=-10) + if not force: + break + + for vertex in vertices: + load_direction[index_vertex[vertex]] = force + # Here we should add a vector to the Scene showing the load case that we are maximizing. + + add_loads = rs.GetString(message="Apply Loads on additional vertices?", strings=["Yes", "No"]) + rs.UnselectAllObjects() + + if add_loads == "Yes": + pass + else: + break + + analysis = Analysis.create_max_load_analysis(formdiagram, envelope, load_direction=load_direction, solver="SLSQP", max_lambd=9999) + + elif objective == "SupportDisplacement": + supports = list(formobject.diagram.supports()) + nb = len(supports) + displacement_array = zeros((nb, 3)) + + 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]") + + if not displ: + break + + if len(displ_list) != 3: + print("provide a 3x1 vector as shown as the example") + break + + displ_list = ast.literal_eval(displ) + + for vertex in vertices: + displacement_array[supports.index(vertex)] = array(displ_list) + # 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 add_vector == "Yes": + pass + else: + break + + analysis = Analysis.create_compl_energy_analysis(formdiagram, envelope, solver="SLSQP", support_displacement=displacement_array) elif objective == "Bestfit": analysis = Analysis.create_bestfit_analysis(formdiagram, envelope) @@ -60,6 +136,7 @@ def RunCommand(): else: raise NotImplementedError + analysis.optimiser.settings["printout"] = True # need to be true so people see the fopt. analysis.apply_selfweight() analysis.apply_envelope() analysis.set_up_optimiser()