def initializeLatticeShell(startPoint, latticeParam, xHexagons, yHexagons, force=10, theta=0, elasticModulus=17000000000, moment=5000000, area=0.0005, g=0, invertHex=True, saveDir=None): ''' This function takes in initial parameters for a hexagon lattice, creates a mesh structure using the anaStruct library object SystemElements(). First, the center points of hexagons in the lattice will be generated, the hexagon vertices will be saved in a custom NumPy array to save the center points and al 6 vertices. The numpy array will hold 7 tuples( 1 tuple for the center-point, 6 tuples for coordinates of each hexagon vertex. ) Args: (startPoint): (tuple): Tuple of dtype=np.float64 or dtype=np.float32 housing the original start point (bottom left) of the hexagon lattice to be constructed. (latticeParam): (float): The length of each 'sub triangle' length starting from the center of the hexagon to each vertex. (xHexagons): (int): Number of hexagons to be constructed in the x-direction in the lattice. (yHexagons): (int): Number of hexagons to be constructed in the y-direction in the lattice. Returns: (lattice): (SystemElements() Object): The system elements object containing all trusses defined and fully constrained. (lattice_coordinatews): (numpy array): Custom numpy array of shape=( xHexagons, yHexagons, 7, 2 ). Contains 7 coordinates per hexagon: Center coords, and vertex coordinates. ''' # Initialize finite element material parameters EA = elasticModulus * area EI = elasticModulus * moment # Initialize timer start = timeit.default_timer() # Initialize anaStruct.py SystemElements() object... # ss = SystemElements(figsize=(12,8), EA=15000.0, EI=5e3) ss = SystemElements(EA=EA, EI=EI) ''' EA - Standard axial stiffness of element EI - Standard bending stiffness of elements figsize - Matplotlibs standard figure size (inches) ''' # Initialize custom numpy array... lattice_coordinates = np.empty(shape=(xHexagons + 1, yHexagons, 7, 2)) # Take not of all elements that are already saved so we don't repeat them # Save initialized system elements points as an array to be referenfced when # creating new system elements to the FEM mesh. old_ss = [] # Initialize hexagon lattice centers: lattice_centers = getHexagonLatticeCenters(startPoint, latticeParam, xHexagons, yHexagons, invertHex=invertHex) print(lattice_centers) # Iterate through each hexagon center and fill lattice_coordinates numpy array for j in range(yHexagons): # Every odd numbered row (0 start counting) will have 1 extra hexagon to be drawn in. if j % 2 != 0: xHexagonCount = xHexagons + 1 else: xHexagonCount = xHexagons for i in range(xHexagonCount): # Get hexagon points curr_hexPoints = hexagonPoints(lattice_centers[i, j], latticeParam, invertHex=invertHex) # Initialize start point lattice_coordinates[i, j, 0] = lattice_centers[i, j] lattice_coordinates[i, j, 1:] = curr_hexPoints # Iterating through first hexagon being drawn if i == 0: # For even values: if j % 2 != 0: # Finds the point pair list of the right half of the hexagon point_pair_list = [ (curr_hexPoints[1], curr_hexPoints[0]), (curr_hexPoints[0], curr_hexPoints[5]), (curr_hexPoints[5], curr_hexPoints[4]), ] for k in range(3): # Check if current element is already added is_added, index = checkSystemElement( point_pair_list[k][0], point_pair_list[k][1], old_ss) # Check if element exists if is_added == False: ss.add_element(location=[ point_pair_list[k][0], point_pair_list[k][1] ], EA=EA, EI=EI, g=g) old_ss.append( (point_pair_list[k][0], point_pair_list[k][1])) else: print( "Point Pair {} has already been added at index {} of old_ss list." .format(curr_point_pair, index)) else: # Iterate through all point pairs: for k in range(6): curr_point_pair = (curr_hexPoints[k - 1], curr_hexPoints[k]) is_added, index = checkSystemElement( curr_point_pair[0], curr_point_pair[1], old_ss) # If element doesn't already exist, add it to the mesh if is_added == False: ss.add_element(location=[ curr_hexPoints[k - 1], curr_hexPoints[k] ], EA=EA, EI=EI, g=g) old_ss.append( (curr_hexPoints[k - 1], curr_hexPoints[k])) else: # save elements added # old_ss.append( curr_hexPoints[k-1], curr_hexPoints[k] ) # testing line -------------------- print( "Point Pair {} has already been added at index {} of old_ss list." .format(curr_point_pair, index)) # end testing line ------------------ elif j % 2 != 0 and i == xHexagons: # Uneven row numbers if j % 2 != 0: # Finds the point pair list of the right half of the hexagon point_pair_list = [ (curr_hexPoints[1], curr_hexPoints[2]), (curr_hexPoints[2], curr_hexPoints[3]), (curr_hexPoints[3], curr_hexPoints[4]), ] for k in range(3): # Check if current element is already added is_added, index = checkSystemElement( point_pair_list[k][0], point_pair_list[k][1], old_ss) # Check if element exists if is_added == False: ss.add_element(location=[ point_pair_list[k][0], point_pair_list[k][1] ], EA=EA, EI=EI, g=g) old_ss.append( (point_pair_list[k][0], point_pair_list[k][1])) else: print( "Point Pair {} has already been added at index {} of old_ss list." .format(curr_point_pair, index)) # Even hexagon values: else: for k in range(6): # check if current element is already added...if not, add it! curr_point_pair = (curr_hexPoints[k - 1], curr_hexPoints[k]) is_added, index = checkSystemElement( curr_point_pair[0], curr_point_pair[1], old_ss) # If element doesn't already exist, add it to the mesh if is_added == False: ss.add_element(location=[ curr_hexPoints[k - 1], curr_hexPoints[k] ], EA=EA, EI=EI, g=g) old_ss.append( (curr_hexPoints[k - 1], curr_hexPoints[k])) else: # save elements added # old_ss.append( curr_hexPoints[k-1], curr_hexPoints[k] ) # testing line -------------------- print( "Point Pair {} has already been added at index {} of old_ss list." .format(curr_point_pair, index)) # end testing line ------------------ # add all system elements and save point pairs else: for k in range(6): # check if current element is already added...if not, add it! curr_point_pair = (curr_hexPoints[k - 1], curr_hexPoints[k]) is_added, index = checkSystemElement( curr_point_pair[0], curr_point_pair[1], old_ss) # If element doesn't already exist, add it to the mesh if is_added == False: ss.add_element(location=[ curr_hexPoints[k - 1], curr_hexPoints[k] ], EA=EA, EI=EI, g=g) old_ss.append( (curr_hexPoints[k - 1], curr_hexPoints[k])) else: # save elements added # old_ss.append( curr_hexPoints[k-1], curr_hexPoints[k] ) # testing line -------------------- print( "Point Pair {} has already been added at index {} of old_ss list." .format(curr_point_pair, index)) # end testing line ------------------ end = timeit.default_timer() total_time = np.round((end - start), 2) print( "\n\nGenerating hexagon mesh of x-y dimensions, {}-{}, lattice parameter, {}, took {} seconds.\n\n" .format(xHexagons, yHexagons, latticeParam, total_time)) lowest_nodes = findLowestNodes(ss, startPoint, latticeParam, xHexagons, yHexagons) highest_nodes = findHighestNodes(ss, startPoint, latticeParam, xHexagons, yHexagons) # add supports and flattening elements for i in range(len(lowest_nodes)): ss.add_element(location=[lowest_nodes[i - 1][1], lowest_nodes[i][1]]) old_ss.append((lowest_nodes[i - 1], lowest_nodes[i])) # add fixed support on lowest nodes... ss.add_support_fixed(node_id=lowest_nodes[i][0]) # add forces and node locations for i in range(len(highest_nodes)): ss.add_element(location=[highest_nodes[i - 1][1], highest_nodes[i][1]]) old_ss.append((highest_nodes[i - 1], highest_nodes[i])) # add forces at highest nodes... # ss.q_load(q=-1, element_id=highest_nodes[i], direction='element') ss.point_load(node_id=highest_nodes[i][0], Fx=0, Fy=force, rotation=theta) # Solve and time it solveTimeStart = np.round(timeit.default_timer(), 2) ss.solve() solveTimeEnd = np.round(timeit.default_timer(), 2) total_solve_time = solveTimeEnd - solveTimeStart print( "\n\nSolving beam element model of x-y dimensions, {}-{}, lattice parameter, {}, took {} seconds.\n\n" .format(xHexagons, yHexagons, latticeParam, total_solve_time)) # Calculate average displacement of nodes totalDisplacement = 0 displacements = ss.get_node_displacements(node_id=0) for i in range(len(displacements)): totalDisplacement += np.sqrt(displacements[i][1]**2 + displacements[i][2]**2) averageDisplacements = totalDisplacement / len(displacements) print("\n\nAverage Node Displacement: {}mm".format(averageDisplacements * 1000)) if saveDir != None: diagnosticData = [] diagnosticData.append( "Hexagon Lattice ({}-x-hexagons,{}-y-hexagons)\n".format( xHexagons, yHexagons)) diagnosticData.append("Lattice Parameter: {}mm\n".format(latticeParam)) diagnosticData.append("Force: {}N\n".format(force)) diagnosticData.append("Elastic Modulus: {}MPa\n".format( elasticModulus / 1000)) diagnosticData.append("Second Moment of Area: {}\n".format(moment)) diagnosticData.append("Area: {}mm\n".format(area * 1000)) diagnosticData.append("Bending Stiffness: {}\n".format(elasticModulus * moment)) diagnosticData.append( "Average Displacement: {}mm\n".format(averageDisplacements)) diagnosticData.append("Mesh Generated in {}s\n".format(total_time)) diagnosticData.append( "Beam Element Model Solved in {}s\n".format(total_solve_time)) folderDir = snr.createFolder( saveDir, "a={}mm A={}mm f={}N E={}MPa".format(latticeParam, area, force, elasticModulus / 1000)) textFile = open("{}\\diagnostics.txt".format(folderDir), 'w') textFile.writelines(diagnosticData) textFile.close() # beam element model is solved in the call of this function. saveElementModel( ss, folderDir, "a={}mm A={}mm f={}N E={}MPa".format(latticeParam, area, force, elasticModulus / 1000)) return ss
def trussbridge(Ediag, Adiag, Ebot, Abot, Etop, Atop, p, w_tri=4, h_tri=2, num_tri=6, disp=False): """ Calculate displacement of middle point in bridge truss Args: Ediag (list): list of Young's modulus for each pair of diagonal trusses (Pa) Adiag (list): list of cross-sectional area for each pair of diagonal trusses (m2) Ebot (list): list of Young's modulus for each bottom truss (Pa) Abot (list): list of cross-sectional area for each bottom truss (m2) Etop (list): list of Young's modulus for each top truss (Pa) Atop (list): list of cross-sectional area for each top truss (m2)t p (list): list of force applied on the top nodes (N) num_tri (int): number of triangles disp (bool): display image or not """ Ediag = np.array(Ediag) Adiag = np.array(Adiag) Ebot = np.array(Ebot) Abot = np.array(Abot) Etop = np.array(Etop) Atop = np.array(Atop) EAdiag = Ediag * Adiag EAbot = Ebot * Abot EAtop = Etop * Atop ss = SystemElements() # Triangle coord x_base = np.arange(0, num_tri + 1) * w_tri x_top = np.arange(0, num_tri) * w_tri + h_tri y = np.ones(num_tri) * h_tri # Create 6 triangles for i in range(num_tri): p1 = [x_base[i], 0] p2 = [x_top[i], y[i]] p3 = [x_base[i + 1], 0] ss.add_truss_element(location=[p1, p2], EA=EAdiag[i]) ss.add_truss_element(location=[p2, p3], EA=EAdiag[i]) ss.add_truss_element(location=[p1, p3], EA=EAbot[i]) # Create 5 horizontal trusses for i in range(num_tri - 1): ss.add_truss_element(location=[[x_top[i], y[i]], [x_top[i + 1], y[i + 1]]], EA=EAtop[i]) # Create support ss.add_support_hinged(node_id=1) ss.add_support_roll(node_id=13, direction=2) # Create Load loadnode = [2, 4, 6, 8, 12] for index, point in enumerate(loadnode): ss.point_load(node_id=point, Fy=p[index]) ss.point_load(node_id=point, Fy=p[index]) ss.point_load(node_id=point, Fy=p[index]) ss.point_load(node_id=point, Fy=p[index]) ss.solve() disp7 = ss.get_node_displacements(node_id=7) if disp is True: ss.show_axial_force() ss.show_displacement(factor=10) return disp7