def display_truss_design(x): """ find the displacements in the specified truss as well as the weight of the truss :param x: the defining parameters of the truss. a list of values, in the order on/off, beam number :return: """ ss = SystemElements() beam_locations = [] side_length = 120 beam_locations.append([[0, 0], [0, side_length]]) beam_locations.append([[0, side_length], [side_length, side_length]]) beam_locations.append([[side_length, side_length], [side_length, 0]]) beam_locations.append([[side_length, 0], [0, side_length]]) beam_locations.append([[0, 0], [side_length, side_length]]) for i, beam in enumerate(beam_locations): if x[i * 2]: area = a[x[i * 2 + 1]] ss.add_element(location=beam, EA=e * area, EI=e * ix[x[i * 2 + 1]]) ss.add_support_fixed(node_id=1) ss.add_support_roll(node_id=4) ss.point_load(Fx=50, node_id=2) ss.point_load(Fz=-50, node_id=3) ss.solve() # ss.show_structure() ss.show_displacement() return
def plot_truss(x): ss = SystemElements() p1 = Vertex(0, 0) p2 = Vertex(x[30], 0) p3 = Vertex(240, 0) p4 = Vertex(x[31], 0) p5 = Vertex(480, 0) p6 = Vertex(x[32], x[33]) p7 = Vertex(x[34], x[35]) p8 = Vertex(x[36], x[37]) verticies = [p1, p2, p3, p4, p5, p6, p7, p8] members = [(0, 1), (1, 2), (2, 3), (3, 4), (0, 5), (1, 5), (2, 5), (5, 6), (1, 6), (2, 6), (3, 6), (6, 7), (2, 7), (3, 7), (4, 7)] weight = 0 for i in range(0, 30, 2): if x[i]: start = verticies[members[int(i / 2)][0]] end = verticies[members[int(i / 2)][1]] length = calc_length(start, end) area = a[x[i + 1]] Ix = ix[x[i + 1]] weight += length * area * dens EI = e * Ix EA = e * area ss.add_element(location=[start, end], EA=EA, EI=EI) ss.add_support_hinged(1) ss.add_support_roll(3) ss.add_support_roll(5) # ss.q_load(element_id=[1, 2, 3, 4], q=-0.1) ss.point_load(node_id=[2, 4], Fz=[-100000, -100000]) ss.solve() # ss.show_structure() ss.show_displacement()
def build(self): builds = np.zeros(self.pop_size, dtype=object) middle_node = np.zeros(self.pop_size, dtype=int) all_lengths = np.zeros(self.pop_size, dtype=int) n_elements = np.zeros(self.pop_size, dtype=int) for i in range(self.pop.shape[0]): ss = SystemElements() on = np.argwhere(self.pop[i] == 1) for j in on.flatten(): n1, n2 = self.comb[j] l1 = self.loc[n1] l2 = self.loc[n2] ss.add_element([l1, l2]) # add mirror ss.add_element([ mirror(l1, self.mirror_line), mirror(l2, self.mirror_line) ]) # Placing the supports on the outer nodes, and the point load on the middle node. x_range = ss.nodes_range('x') if len(x_range) <= 2: builds[i] = None all_lengths[i] = 0 n_elements[i] = 0 else: length = max(x_range) start = min(x_range) ids = list(ss.node_map.keys()) max_node_id = ids[np.argmax(x_range)] for j in range(self.height): middle_node_id = ss.nearest_node( "both", np.array([(length + start) / 2, self.height - j])) if middle_node_id: break if middle_node_id is None: middle_node_id = ids[np.argmin( np.abs(np.array(x_range) - (length + start) / 2))] ss.add_support_hinged(1) ss.add_support_hinged(max_node_id) ss.point_load(middle_node_id, Fz=-100) builds[i] = ss middle_node[i] = middle_node_id all_lengths[i] = length n_elements[i] = on.size self.builds = builds return builds, middle_node, all_lengths, n_elements
def solve_truss(x): ss = SystemElements() p1 = Vertex(0, 0) p2 = Vertex(x[30], 0) p3 = Vertex(240, 0) p4 = Vertex(x[31], 0) p5 = Vertex(480, 0) p6 = Vertex(x[32], x[33]) p7 = Vertex(x[34], x[35]) p8 = Vertex(x[36], x[37]) verticies = [p1, p2, p3, p4, p5, p6, p7, p8] members = [(0, 1), (1, 2), (2, 3), (3, 4), (0, 5), (1, 5), (2, 5), (5, 6), (1, 6), (2, 6), (3, 6), (6, 7), (2, 7), (3, 7), (4, 7)] weight = 0 for i in range(0, 30, 2): if x[i]: start = verticies[members[int(i / 2)][0]] end = verticies[members[int(i / 2)][1]] length = calc_length(start, end) area = a[x[i + 1]] Ix = ix[x[i + 1]] weight += length * area * dens EI = e * Ix EA = e * area ss.add_element(location=[start, end], EA=EA, EI=EI) ss.add_support_hinged(1) ss.add_support_roll(3) ss.add_support_roll(5) # ss.q_load(element_id=[1, 2, 3, 4], q=-0.1) ss.point_load(node_id=[2, 4], Fz=[-10000, -10000]) try: ss.solve() # ss.show_structure() # ss.show_reaction_force() # ss.show_displacement() displ = ss.get_node_displacements() phi_1 = np.abs(displ[0][3]) d2x = np.abs(displ[1][1]) d2y = np.abs(displ[1][2]) d3x = np.abs(displ[2][1]) d4x = np.abs(displ[3][1]) d4y = np.abs(displ[3][2]) d5x = np.abs(displ[4][1]) avg = np.average(np.array([d2x, d2y, d3x, d4x, d4y, d5x])) fitness = [avg, weight] except: fitness = [999, 99999999] # print(weight) # print(ss.get_node_displacements()) return fitness
def truss_constraints(x): """ find the displacements in the specified truss as well as the weight of the truss :param x: the defining parameters of the truss. a list of values, in the order on/off, beam number :return: """ ss = SystemElements() weight = 0 max_displ = 0.5 max_weight = 500 beam_locations = [] side_length = 120 beam_locations.append([[0, 0], [0, side_length]]) beam_locations.append([[0, side_length], [side_length, side_length]]) beam_locations.append([[side_length, side_length], [side_length, 0]]) beam_locations.append([[side_length, 0], [0, side_length]]) beam_locations.append([[0, 0], [side_length, side_length]]) for i, beam in enumerate(beam_locations): if x[i * 2]: length = calc_length(beam) area = a[x[i * 2 + 1]] weight += area * dens * length ss.add_element(location=beam, EA=e * area, EI=e * ix[x[i * 2 + 1]]) ss.add_support_fixed(node_id=1) ss.add_support_roll(node_id=4) ss.point_load(Fx=50, node_id=2) ss.point_load(Fz=-50, node_id=3) ss.solve() # ss.show_structure() # ss.show_displacement() node_disp = [] displacements = ss.get_node_displacements() for (node, ux, uy, phi) in displacements: displ = np.sqrt(ux**2 + uy**2) displ = (displ - max_displ) / max_displ node_disp.append(displ) weight = (weight - max_weight) / max_weight node_disp.append(weight) return node_disp
from anastruct.fem.system import SystemElements ss = SystemElements(EI=5e3, EA=1e5) ss.add_multiple_elements([[0, 0], [0, 10]], 10) top_node = ss.nearest_node('y', 10) + 1 ss.add_support_roll(top_node, 1) ss.add_support_hinged(1) ss.point_load(top_node, Fz=-1) if __name__ == "__main__": print(ss.solve(geometrical_non_linear=True)) ss.show_displacement()
from anastruct.fem.system import SystemElements from anastruct import LoadCase, LoadCombination import matplotlib.pyplot as plt import numpy as np ss = SystemElements() height = 10 x = np.cumsum([0, 4, 7, 7, 4]) y = np.zeros(x.shape) x = np.append(x, x[::-1]) y = np.append(y, y + height) ss.add_element_grid(x, y) ss.add_element([[0, 0], [0, height]]) ss.add_element([[4, 0], [4, height]]) ss.add_element([[11, 0], [11, height]]) ss.add_element([[18, 0], [18, height]]) ss.add_support_hinged([1, 5]) ss.show_structure() lc_wind = LoadCase("wind") lc_wind.q_load(q=-1, element_id=[10, 11, 12, 13, 5]) print(lc_wind) ss.apply_load_case(lc_wind) ss.show_structure() # reset the structure
from anastruct.fem.system import SystemElements ss = SystemElements(mesh=10) ss.add_element([10, 0]) ss.add_element([20, 0]) ss.q_load(-10, [1, 2]) ss.add_support_hinged([1, 2, 3]) if __name__ == "__main__": ss.solve() for el in ss.element_map.values(): print(el.deflection.max()) ss.show_results()
from anastruct.fem.system import SystemElements import numpy as np ss = SystemElements(EA=15000, EI=5000) # Add beams to the system. ss.add_element(location=[[0, 0], [0, 5]]) ss.add_element(location=[[0, 5], [5, 5]]) ss.add_element(location=[[5, 5], [5, 0]]) ss.add_element(location=[[5, 0], [0, 5]]) # Add a fixed support at node 1. ss.add_support_fixed(node_id=1) # Add a rotational spring support at node 4. ss.add_support_fixed(node_id=4) # Add loads. ss.point_load(Fx=30, node_id=2) ss.q_load(q=-20, element_id=2) # Solve ss.solve() # Get visual results. # ss.show_structure() # ss.show_reaction_force() # ss.show_axial_force() # ss.show_shear_force() # ss.show_bending_moment() # ss.show_displacement()
from anastruct.fem.system import SystemElements ss = SystemElements(mesh=250) ss.add_element(location=[(0, 0), (1.33, 0)], EA=356, EI=1332) ss.add_element(location=[(1.33, 0), (2.0, 0)], EA=356, EI=1332) ss.add_support_hinged(node_id=ss.find_node_id((0, 0))) ss.add_support_hinged(node_id=ss.find_node_id((1.33, 0))) ss.q_load(q=-1000.0, element_id=1, direction="y") ss.q_load(q=-1000.0, element_id=2, direction="y") if __name__ == "__main__": ss.solve() ss.show_displacement()
def build_single_bridge(dna, comb, loc, height, get_ss=False, unit="deflection", EI=15e3, roll=True, support_btm=False, es=False): """ Build a single bridge structure. :param dna: (array) DNA from population. :param comb: (array) All possible combinations. :param loc: (array) All possible locations. :param height: (int) Maximum height of the bridge. :param unit: (str) Make this important in the fitness score evaluation. {deflection, axial compression, tension, moment) :param EI: (flt) Bending stiffness of the structure. :param roll: (bool) Add a support that is free in x. :param support_btm: (bool) Place the support at the bottom of the grid. :param es: (bool) Special code for Evolution Strategies. :return: (unit, length, number of elements) """ ss = SystemElements(EI=EI, mesh=3) on = np.argwhere(dna == 1).flatten() # Add the elements based on the dna mirror_line = 0 for j in on: n1, n2 = comb[j] l1 = loc[n1] l2 = loc[n2] ss.add_element([l1, l2]) mirror_line = max(mirror_line, l1[0], l2[0]) # add mirrored element for j in on: n1, n2 = comb[j] l1 = loc[n1] l2 = loc[n2] ss.add_element([mirror(l1, mirror_line), mirror(l2, mirror_line)]) # Placing the supports on the outer nodes, and the point load on the middle node. x_range = ss.nodes_range('x') # A bridge of one element is no bridge, it's a beam. if len(x_range) <= 2: return None else: length = max(x_range) start = min(x_range) ids = list(ss.node_map.keys()) # Find the ids of the middle node for the force application, # and the most right node for the support of the bridge max_node_id = ids[np.argmax(x_range)] for j in range(height): middle_node_id = ss.nearest_node( "both", np.array([(length + start) / 2, height - j])) if middle_node_id: break if middle_node_id is None: middle_node_id = ids[np.argmin( np.abs(np.array(x_range) - (length + start) / 2))] # Find the support ids in case the supports should be place in the middle. if support_btm: left_node_id = 1 right_node_id = max_node_id else: idx = np.argsort(np.abs(np.arange(height) - height // 2)) for j in idx: left_node_id = ss.nearest_node("both", np.array([start, j])) if left_node_id: break for j in idx: right_node_id = ss.nearest_node("both", np.array([start + length, j])) if right_node_id: break # Add support conditions ss.add_support_hinged(left_node_id) if roll and right_node_id is not None: ss.add_support_roll(right_node_id) elif right_node_id is not None: ss.add_support_hinged(right_node_id) ss.point_load(middle_node_id, Fz=-100) if ss.validate(): if get_ss: return ss ss.solve() if unit == "deflection": val = np.abs(ss.get_node_displacements(middle_node_id)["uy"]) elif unit == "axial compression": val = -np.min(ss.get_element_result_range("axial")) elif unit == "tension": val = np.max(ss.get_element_result_range("axial")) elif unit == "moment": val = np.abs((ss.get_element_result_range("moment"))) else: raise LookupError("Unit is not defined") if es: return val, length - start, on.size, max(ss.nodes_range('y')) return val, length - start, on.size
import math from anastruct.fem.system import SystemElements ss = SystemElements(EA=5000) ss.add_truss_element(location=[[0, 0], [0, 5]]) ss.add_truss_element(location=[[0, 5], [5, 5]]) ss.add_truss_element(location=[[5, 5], [5, 0]]) ss.add_truss_element(location=[[0, 0], [5, 5]], EA=5000 * math.sqrt(2)) ss.add_support_hinged(node_id=1) ss.add_support_hinged(node_id=4) ss.point_load(Fx=10, node_id=2) ss.solve() ss.show_structure() ss.show_reaction_force() ss.show_axial_force() ss.show_shear_force() ss.show_displacement(factor=10)
from anastruct.fem.system import SystemElements ss = SystemElements(plot_backend="plotly") ss.add_element([[0, 0], [1, 0]]) ss.add_element([2, 0]) ss.add_support_hinged(1) ss.add_support_spring(3, 2, 3000) ss.point_load(2, Fz=-1000) ss.solve() ss.show_structure() ss.show_bending_moment() ss.show_displacement()
from anastruct.fem.system import SystemElements from anastruct.material.profile import HEA from anastruct.material.units import to_kNm2, to_kN load_factor = 3 E = 210e3 profile = HEA[180] EA = to_kN(E * profile["A"]) EI = to_kNm2(E * profile["Iy"]) mp = profile["Wy"] * 235 * 1e-6 ss = SystemElements(EA=EA, EI=EI, load_factor=load_factor) ss.add_element([[0, 0], [0, 4]], mp={2: mp}) ss.add_element([0, 8], mp={1: mp, 2: mp}) ss.add_element([2, 8], mp={1: mp, 2: mp}) ss.add_element([4, 8], mp={1: mp, 2: mp}) ss.add_element([4, 4], mp={1: mp, 2: mp}) ss.add_element([4, 0], mp={1: mp, 2: mp}) ss.add_truss_element([[0, 4], [4, 4]]) ss.add_support_hinged(1) ss.add_support_fixed(7) ss.q_load(-20, 3) ss.q_load(-20, 4) ss.q_load(-1, 1) ss.q_load(-1, 2) if __name__ == "__main__": import time from copy import deepcopy
data = [] # 10 miljoen een ligger met verschillende eigenschappen optimaliseren for i in range(1000000): print(i) # De eigenschappen van de balk worden willekeurig gekozen. De eigenschappne zijn de overspanning, # de afstand waarop de puntlast aangrijpt en de groote van de puntlast en de q-last. De willekeurig gekozen # eigenschappen liggen wel tussen bepaalde waardes en worden afgerong op 1 decimaal overspanning = round(random.uniform(0.1, 25), 1) afstand_puntlast = overspanning * round(random.uniform(0.1, 0.9), 1) puntlast = round(random.uniform(-2, -100), 1) qlast = round(random.uniform(-10, -40), 1) # De constructie bestaat uit 1 element, dus het traagheidsmoment en het oppervlakte van het profiel hebben geen # invloed op de oplegreacties ed. Vandaar dat de stijfehedn ed voor het gemak zo worden verklaard. ss = SystemElements(EA=EA, EI=EI) # Construeren van het element. het element wordt in twee delen opgedeeld omdat Anastruct geen puntlast op afstanden # tot knopen toe laat, maar alleen op knopen zelf. ss.add_element(location=[[0, 0], [afstand_puntlast, 0]]) ss.add_element(location=[[afstand_puntlast, 0], [overspanning, 0]]) # Toevoegen van opleggingen. Een vast scharnier en een rolscharnier. het systeem is statisch bepaald. ss.add_support_hinged(node_id=1) ss.add_support_roll(node_id=3) # Toevoegen van de lasten. De puntlast grijpt aan op de middelste knoop, een willekeurige afstand dus. ss.point_load(node_id=2, Fz=puntlast) ss.q_load(q=qlast, element_id=1) # Uitrekenen van de constructie. De resultaten worden opgeslagen onder resultaten.
def krachten_en_verplaatsingen_elementen(self, belastingcombi): # Belasting combi is een dict. Op deze wijze worden de van toepassing zijnde factoren bepaald. factor_wind = belastingcombi.get('factor veranderlijk wind') factor_permanent = belastingcombi.get('factor permanent') factor_dak_ver = belastingcombi.get('factor veranderlijk dak') # Opstarten van een constructie taak. Anastruct standaard opzet. ss = SystemElements() # Creeren elementen voor liggers en kolommen, met bijbehorende EA en EI. ss.add_element(location=[[0, 0], [0, self.hoogte]], EA=to_kN(E * self.A_kolommen), EI=to_kNm2(E * self.I_kolommen)) ss.add_element(location=[[0, self.hoogte], [self.overspanning, self.hoogte]], EA=to_kN(E * self.A_ligger), EI=to_kNm2(E * self.I_ligger)) ss.add_element(location=[[self.overspanning, self.hoogte], [self.overspanning, 0]], EA=to_kN(E * self.A_kolommen), EI=to_kNm2(E * self.I_kolommen)) # Toevoegen verbindingen. ss.add_support_hinged(node_id=1) ss.add_support_hinged(node_id=4) # Veranderlijke windbelasting kolom. ss.q_load(q=-factor_wind * self.hoh, element_id=1) # Veranderlijke en permanente lasten ligger. ss.q_load(q=-factor_permanent * 2 * self.hoh - factor_permanent * self.EG_profiel_ligger - factor_dak_ver * 1.5 * self.hoh, element_id=2) # Vaste belastingen kolommen ss.point_load(node_id=2, Fz=-factor_permanent * self.EG_profiel_kolommen * self.hoogte) ss.point_load(node_id=3, Fz=-factor_permanent * self.EG_profiel_kolommen * self.hoogte) # Oplossen constructie. Onder elements worden resultaten opgeslagen, heeft de structuur van een dict. ss.solve() elements = ss.get_element_results() # Als de functie wordt aangeroepen voor de krachten op de elementen. Is te zien aan de factoren. if factor_wind is not 1 and factor_dak_ver is not 1: # Maatgevende krachten per element bepalen, die geranschikt worden opgeslagen in een lijst. De eerste kracht # in de lijst correspondeert met het eerste element van het portaal. moment = maximaal_moment(elements) dwarskracht = ss.get_element_result_range("shear") normaalkracht = ss.get_element_result_range("axial") # De krachten per element wordne nu in een dict opgeslagen. Dit ziet er als volgt uit: # {"dwarskracht": [25.0, 53.9, 7.8] etc. krachten_elementen = { "dwarskracht": dwarskracht, "normaalkracht": normaalkracht, "moment": moment } return krachten_elementen # Anders wordt de functie aangeroepen voor verplaatsingen. else: # Verkrijgen relatieve doorbuiging. element_doorbuiging = ss.get_element_results() element_doorbuiging = element_doorbuiging[1].get( 'wmin') / self.overspanning # Verkrijgen relatieve verplaatsing. knoop_verplaatsingen = ss.get_node_displacements() knoop_verplaatsingen = knoop_verplaatsingen[1][3] / self.hoogte return element_doorbuiging, knoop_verplaatsingen