def horizontal_nodal_proxy(formdata, forcedata, *args, **kwargs): """RPC proxy for node-per-node calculation of horizontal equilibrium. Parameters ---------- formdata : dict The data dictionary of a :class:`FormDiagram`. forcedata : dict The data dictionary of a :class:`ForceDiagram`. Additional Parameters --------------------- alpha : int, optional Weighting factor for computing target vectors for parallelisation of corresponding edges of Form and ForceDiagram. Default is `100` which means that the target vectors are equal to the FormDiagram edges. kmax : int, optional Maximum number of iterartions. Default is `100`. display : bool, optional Display all messages generated by the solver. Default is `True`. Returns ------- tuple 0. The updated data dict of the FormDiagram. 1. The updated data dict of the ForceDiagram. """ form = FormDiagram.from_data(formdata) force = ForceDiagram.from_data(forcedata) horizontal_nodal(form, force, *args, **kwargs) return form.to_data(), force.to_data()
def HorizontalEquilibrium_fromData(formdata, forcedata, alpha=100, kmax=100): # *args, **kwargs form = FormDiagram.from_data(deepcopy(formdata)) force = ForceDiagram.from_data(deepcopy(forcedata)) horizontal_nodal(form, force, alpha, kmax) formdata, forcedata = form.to_data(), force.to_data() return formdata, forcedata
def from_vertices_and_faces(vs, fs): mesh = Mesh.from_vertices_and_faces(vs, fs) form = FormDiagram.from_mesh(mesh) corners = list(form.vertices_where({'vertex_degree': 2})) form.vertices_attribute('is_anchor', True, keys=corners) form.edges_attribute('q', 10.0, keys=form.edges_on_boundary()) relax_boundary_openings(form, corners) form.update_boundaries() force = ForceDiagram.from_formdiagram(form) horizontal_nodal(form, force, alpha=95) scale = vertical_from_zmax(form, 450.0) return form
import compas_tna from compas_tna.diagrams import FormDiagram from compas_tna.diagrams import ForceDiagram from compas_tna.equilibrium import horizontal_nodal from compas_plotters import MeshPlotter FILE = compas_tna.get('tutorial/boundaryconditions.json') form = FormDiagram.from_json(FILE) force = ForceDiagram.from_formdiagram(form) horizontal_nodal(form, force, kmax=100) # ============================================================================== # Visualise # ============================================================================== plotter = MeshPlotter(force, figsize=(12, 8), tight=True) vertexcolor = { key: (1.0, 0.9, 0.9) for key in force.vertices() if not form.face_attribute(key, '_is_loaded') } radius = {key: 0.05 for key in force.vertices()} radius.update({ key: 0.1 for key in force.vertices() if not form.face_attribute(key, '_is_loaded') })
interior = boundaries[1:] form.set_vertices_attribute('is_anchor', True, keys=exterior) form.update_exterior(exterior, feet=1) form.update_interior(interior) # ============================================================================== # create the force diagram force = ForceDiagram.from_formdiagram(form) # ============================================================================== # compute equilibrium horizontal_nodal(form, force) scale = vertical_from_zmax(form, zmax=2) print('scale:', scale) print('zmax:', max(form.get_vertices_attribute('z'))) print('residual:', form.residual()) # ============================================================================== # visualise the result viewer = FormViewer(form, figsize=(14, 9)) viewer.draw_vertices(keys=list(form.vertices_where({'is_external': False})), text={ key: "{:.1f}".format(attr['z'])
import compas_tna from compas_tna.diagrams import FormDiagram from compas_tna.diagrams import ForceDiagram from compas_tna.equilibrium import horizontal_nodal from compas_tna.equilibrium import vertical_from_zmax from compas_plotters import MeshPlotter from compas.utilities import i_to_black FILE = compas_tna.get('tutorial/boundaryconditions.json') form = FormDiagram.from_json(FILE) force = ForceDiagram.from_formdiagram(form) horizontal_nodal(form, force, alpha=100) scale = vertical_from_zmax(form, 3.0) # ============================================================================== # visualise # ============================================================================== # draw pipe diagram # and actual reaction forces z = form.vertices_attribute('z') zmin = min(z) zmax = max(z) plotter = MeshPlotter(form, figsize=(12, 8), tight=True) plotter.draw_vertices(keys=list(form.vertices()),
def RunCommand(is_interactive): def redraw(k, xy, edges): if k % conduit.refreshrate: return print(k) conduit.lines = [[[xy[i][1], -xy[i][0]], [xy[j][1], -xy[j][0]]] for i, j in edges] conduit.redraw() scene = get_scene() if not scene: return form = scene.get('form')[0] force = scene.get('force')[0] thrust = scene.get('thrust')[0] if not form: print("There is no FormDiagram in the scene.") return if not force: print("There is no ForceDiagram in the scene.") return kmax = scene.settings['Solvers']['tna.horizontal.kmax'] alpha = scene.settings['Solvers']['tna.horizontal.alpha'] refresh = scene.settings['Solvers']['tna.horizontal.refreshrate'] options = ['Alpha', 'Iterations', 'RefreshRate'] while True: option = compas_rhino.rs.GetString( 'Press Enter to run or ESC to exit.', strings=options) if option is None: print("Horizontal equilibrium aborted!") return if not option: break if option == 'Alpha': alpha_options = ['form{}'.format(int(i * 10)) for i in range(11)] alpha_default = 0 for i in range(11): if alpha == i * 10: alpha_default = i break temp = compas_rhino.rs.GetString('Select parallelisation weight', alpha_options[alpha_default], alpha_options) if not temp: alpha = 100 else: alpha = int(temp[4:]) elif option == 'Iterations': new_kmax = compas_rhino.rs.GetInteger('Enter number of iterations', kmax, 1, 10000) if new_kmax or new_kmax is not None: kmax = new_kmax elif option == 'RefreshRate': new_refresh = compas_rhino.rs.GetInteger( 'Refresh rate for dynamic visualisation', refresh, 0, 1000) if new_refresh or new_refresh is not None: refresh = new_refresh if refresh > kmax: refresh = 0 scene.settings['Solvers']['tna.horizontal.kmax'] = kmax scene.settings['Solvers']['tna.horizontal.alpha'] = alpha scene.settings['Solvers']['tna.horizontal.refreshrate'] = refresh if refresh > 0: conduit = HorizontalConduit([], refreshrate=refresh) with conduit.enabled(): horizontal_nodal(form.datastructure, force.datastructure, kmax=kmax, alpha=alpha, callback=redraw) else: horizontal_nodal(form.datastructure, force.datastructure, kmax=kmax, alpha=alpha) bbox_form = form.datastructure.bounding_box_xy() bbox_force = force.datastructure.bounding_box_xy() xmin_form, xmax_form = bbox_form[0][0], bbox_form[1][0] xmin_force, _ = bbox_force[0][0], bbox_force[1][0] ymin_form, ymax_form = bbox_form[0][1], bbox_form[3][1] ymin_force, ymax_force = bbox_force[0][1], bbox_force[3][1] y_form = ymin_form + 0.5 * (ymax_form - ymin_form) y_force = ymin_force + 0.5 * (ymax_force - ymin_force) dx = 1.3 * (xmax_form - xmin_form) + (xmin_form - xmin_force) dy = y_form - y_force force.datastructure.transform(Translation.from_vector([dx, dy, 0])) force.datastructure.update_angle_deviations() thrust.settings['_is.valid'] = False scene.update() max_angle = max(form.datastructure.edges_attribute('_a')) tol = scene.settings['RV2']['tol.angles'] if max_angle < tol: print('Horizontal equilibrium found!') print('Maximum angle deviation:', max_angle) else: print( 'Horizontal equilibrium NOT found! Consider running more iterations.' ) print('Maximum angle deviation:', max_angle)