def get_node_coords_and_disp(): node_coords = dict() node_disp = dict() node_tags = ops.getNodeTags() for i in node_tags: node_coords[i] = ops.nodeCoord(i) node_disp[i] = ops.nodeDisp(i) return (node_coords,node_disp)
def plot_deformed_shape(self, xlim, ylim, scale=1, arrow_len=10, arrow_width=2, save=''): ''' Plot deformed shape of the model. Args: xlim: A list of left and right limits of the x axis. ylim: A list of bottom and top limits of the y axis. scale: A float scale of the displayed deformations (default=1). arrow_len: An integer length of the load arrows displayed (default=10). arrow_width: An integer head width of the load arrows displayed (default=2). save: A string indicating save path for the figure (default='', meaning that the figure will NOT be saved by default). ''' fig, ax = plt.subplots(dpi=75) ax.set_axis_off() ax.grid(True, which='both', alpha=0.5) ax.axhline(y=0, color='k', lw=1) opsv.plot_defo(scale, fmt_undefo='k-', fmt_interp='k--') ax.axis('equal') ax.set(xlim=xlim, ylim=ylim) node_list = ops.getNodeTags() node_disp = np.array([ops.nodeDisp(n) for n in node_list]) node_coord = np.array([ops.nodeCoord(n) for n in node_list]) new_coord = node_disp[:, :-1] * scale + node_coord for node, Px, Py, M in self.loads: c = new_coord[node_list.index(node), :] ax.annotate('', xytext=(c[0] + abs(Px) * arrow_len, c[1] + abs(Py) * arrow_len), xy=(c[0], c[1]), arrowprops=dict(arrowstyle=f'-|>, \ head_width={arrow_width/5},\ head_length={arrow_width/2}', lw=arrow_width, fc='orangered', ec='orangered')) if save: fig.savefig(save, transparent=True) plt.show()
def _getNodesandElements(): """ This function returns the nodes and elments for an active model, in a standardized format. The OpenSees model must be active in order for the function to work. Returns ------- nodes : 2dArray An array of all nodes in the model. Returns nodes in the shape: [Nodes, 3] in 2d and [Nodes, 4] For each node the information is tored as follows: [NodeID, x, y] or [NodeID, x, y, z] elements : Array An list of all elements in. Each entry in the list is it's own' [element1, element2,...], element1 = [element#, node1, node2,...] """ # Get nodes and elements nodeList = ops.getNodeTags() eleList = ops.getEleTags() # Check Number of dimensions and intialize variables ndm = len(ops.nodeCoord(nodeList[0])) Nnodes = len(nodeList) nodes = np.zeros([Nnodes, ndm + 1]) # Get Node list for ii, node in enumerate(nodeList): nodes[ii, 0] = node nodes[ii, 1:] = ops.nodeCoord(nodeList[ii]) Nele = len(eleList) elements = [None] * Nele # Generate the element list by looping through all emenemts for ii, ele in enumerate(eleList): tempNodes = ops.eleNodes(ele) tempNnodes = len(tempNodes) tempEle = np.zeros(tempNnodes + 1) tempEle[0] = int(ele) tempEle[1:] = tempNodes elements[ii] = tempEle return nodes, elements
def _getModeShapeData(modeNumber): # Get nodes and elements nodeList = ops.getNodeTags() # Check Number of dimensions and intialize variables ndm = len(ops.nodeCoord(nodeList[0])) Nnodes = len(nodeList) nodes_modeshape = np.zeros([Nnodes, ndm + 1]) for ii, node in enumerate(nodeList): nodes_modeshape[ii, 0] = node tempData = ops.nodeEigenvector(nodeList[ii], modeNumber) nodes_modeshape[ii, 1:] = tempData[0:ndm] return nodes_modeshape
def define_geometry(self, nodes, elements, fixities, num_integ=10): ''' Define geometry of the structure (all dimensions are in mm). Args: nodes: A list of nodes in a form [node_tag, coord1, coord2]. elements: A list of elements in a form [ele_tag, node1, node2, disc]. fixities: A list of fixities in a form [node, x, y, z]. num_integ: Number of integration points along each element (default=10) ''' self.nodes = nodes self.elements = elements self.fixities = fixities if self.section == None: raise Exception('No section is defined.') ops.geomTransf('PDelta', 1) ops.beamIntegration('Lobatto', 1, 1, num_integ) for nd in self.nodes: ops.node(*nd) for el in self.elements: ele_tag, node1, node2, disc = el DiscretizeMember.DiscretizeMember(node1, node2, disc, 'forceBeamColumn', 1, 1, nodeTag=len(ops.getNodeTags()) + 1, eleTag=len(ops.getEleTags()) + 1) for fx in self.fixities: ops.fix(*fx)
def get_multi_pile_m( pile_layout, cap_edge=0, cap_thickness=2, pile_z0=-2.5, pile_z1=-30, pile_d=2, m0=7500000, top_f=0.0, top_h=0.0, top_m=0.0 ): if cap_edge == 0: if pile_d <= 1: cap_edge = max(0.25, 0.5 * pile_d) else: cap_edge = max(0.5, 0.3 * pile_d) cap_w = max(pile_layout[0]) - min(pile_layout[0]) + pile_d + cap_edge * 2 cap_l = max(pile_layout[1]) - min(pile_layout[1]) + pile_d + cap_edge * 2 top_f += cap_w * cap_l * cap_thickness * 26e3 # 承台自重 top_f += (cap_w * cap_l) * (-pile_z0 - cap_thickness) * 15e3 # 盖梁重量 pile_rows = len(pile_layout[1]) # 桩排数 top_f /= pile_rows # 桩顶力分配 top_h /= pile_rows # 桩顶水平力分配 top_m /= pile_rows # 桩顶弯矩分配 cap_i = cap_l * cap_thickness ** 3 / 12 / pile_rows # 承台横向刚度 pile_h = pile_z0 - pile_z1 pile_a = np.pi * (pile_d / 2) ** 2 pile_i = np.pi * pile_d ** 4 / 64 pile_b1 = 0.9 * (1.5 + 0.5 / pile_d) * 1 * pile_d # 建立模型 ops.wipe() ops.model('basic', '-ndm', 2, '-ndf', 3) # 建立节点 cap_bot = pile_z0 # ops.node(1, 0, cap_top) # 承台竖向节点 if 0 not in pile_layout[0]: ops.node(2, 0, cap_bot) # 建立桩基节点 node_z = np.linspace(pile_z0, pile_z1, elem_num + 1) for i, j in enumerate(pile_layout[0]): node_start = 100 + i * 300 for m, n in enumerate(node_z): ops.node(node_start + m + 1, j, n) ops.node(node_start + m + 151, j, n) nodes = {} for i in ops.getNodeTags(): nodes[i] = ops.nodeCoord(i) # 建立约束 for i, j in enumerate(pile_layout[0]): node_start = 100 + i * 300 for m, n in enumerate(node_z): ops.fix(node_start + m + 151, 1, 1, 1) if n == node_z[-1]: ops.fix(node_start + m + 1, 1, 1, 1) # 建立材料 for i in range(len(node_z)): pile_depth = i * (pile_h / elem_num) pile_depth_nominal = 10 if pile_depth <= 10 else pile_depth soil_k = m0 * pile_depth_nominal * pile_b1 * (pile_h / elem_num) if i == 0: ops.uniaxialMaterial('Elastic', 1 + i, soil_k / 2) continue ops.uniaxialMaterial('Elastic', 1 + i, soil_k) # 装配 ops.geomTransf('Linear', 1) # 建立单元 if len(pile_layout[0]) > 1: # 承台横向单元 cap_nodes = [] for i in nodes: if nodes[i][1] == cap_bot: if len(cap_nodes) == 0: cap_nodes.append(i) elif nodes[i][0] != nodes[cap_nodes[-1]][0]: cap_nodes.append(i) cap_nodes = sorted(cap_nodes, key=lambda x: nodes[x][0]) for i, j in enumerate(cap_nodes[:-1]): ops.element('elasticBeamColumn', 10 + i, j, cap_nodes[i+1], cap_l * cap_thickness, 3e10, cap_i, 1) pile_elem = [] for i, j in enumerate(pile_layout[0]): # 桩基单元 node_start = 100 + i * 300 pile_elem_i = [] for m, n in enumerate(node_z): if n != pile_z1: ops.element('elasticBeamColumn', node_start + m + 1, node_start + m + 1, node_start + m + 2, pile_a, 3e10, pile_i, 1) pile_elem_i.append(node_start + m + 1) ops.element('zeroLength', node_start + m + 151, node_start + m + 151, node_start + m + 1, '-mat', 1 + m, '-dir', 1) pile_elem.append(pile_elem_i) ops.timeSeries('Linear', 1) ops.pattern('Plain', 1, 1) for i in nodes: if nodes[i] == [0, pile_z0]: ops.load(i, -top_h, -top_f, top_m) # 加载 ops.system('BandGeneral') ops.numberer('Plain') ops.constraints('Plain') ops.integrator('LoadControl', 0.01) ops.test('EnergyIncr', 1e-6, 200) ops.algorithm('Newton') ops.analysis('Static') ops.analyze(100) node_disp = {} for i in ops.getNodeTags(): node_disp[i] = [j * 1000 for j in ops.nodeDisp(i)] elem_m = {} for i in pile_elem: for j in i: elem_m[j] = [k / 1000 for k in ops.eleForce(j)] plt.figure() for i, j in enumerate(pile_elem): plt.subplot(f'1{len(pile_elem)}{i+1}') if i == 0: plt.ylabel('Pile Depth(m)') node_disp_x = [] for m, n in enumerate(j): node_1 = ops.eleNodes(n)[0] if m == 0: plt.plot([0, node_disp[node_1][0]], [nodes[node_1][1], nodes[node_1][1]], linewidth=1.5, color='grey') else: plt.plot([0, node_disp[node_1][0]], [nodes[node_1][1], nodes[node_1][1]], linewidth=0.7, color='grey') node_disp_x.append(node_disp[node_1][0]) for m, n in enumerate(j): node_1 = ops.eleNodes(n)[0] if abs(node_disp[node_1][0]) == max([abs(i) for i in node_disp_x]): side = 1 if node_disp[node_1][0] > 0 else -1 plt.annotate(f'{node_disp[node_1][0]:.1f} mm', xy=(node_disp[node_1][0], nodes[node_1][1]), xytext=(0.4 + 0.1 * side, 0.5), textcoords='axes fraction', bbox=dict(boxstyle="round", fc="0.8"), arrowprops=dict(arrowstyle='->', connectionstyle=f"arc3,rad={side * 0.3}")) break plt.plot([0, 0], [node_z[0], node_z[-1]], linewidth=1.5, color='dimgray') plt.plot(node_disp_x, node_z[:-1], linewidth=1.5, color='midnightblue') plt.xlabel(f'Displacement_{i+1} (mm)') plt.show() plt.figure() for i, j in enumerate(pile_elem): plt.subplot(f'1{len(pile_elem)}{i + 1}') if i == 0: plt.ylabel('Pile Depth(m)') elem_mi = [] for m, n in enumerate(j): node_1 = ops.eleNodes(n)[0] if m == 0: plt.plot([0, elem_m[n][2]], [nodes[node_1][1], nodes[node_1][1]], linewidth=1.5, color='grey') else: plt.plot([0, elem_m[n][2]], [nodes[node_1][1], nodes[node_1][1]], linewidth=0.7, color='grey') elem_mi.append(elem_m[n][2]) for m, n in enumerate(j): node_1 = ops.eleNodes(n)[0] if abs(elem_m[n][2]) == max([abs(i) for i in elem_mi]): side = 1 if elem_m[n][2] > 0 else -1 plt.annotate(f'{elem_m[n][2]:.1f} kN.m', xy=(elem_m[n][2], nodes[node_1][1]), xytext=(0.4 + 0.1 * side, 0.5), textcoords='axes fraction', bbox=dict(boxstyle="round", fc="0.8"), arrowprops=dict(arrowstyle='->', connectionstyle=f"arc3,rad={side * 0.3}")) break plt.plot([0, 0], [node_z[0], node_z[-1]], linewidth=1.5, color='dimgray') plt.plot(elem_mi, node_z[:-1], linewidth=1.5, color='brown') plt.xlabel(f'Moment_{i + 1} (kN.m)') plt.show() return pile_elem, elem_m
def ModalAnalysis3D(numEigen): """ |-----------------------------------------------------------------------| | | | Modal Analysis of 3D systems | | | | Author: Volkan Ozsarac | | Affiliation: University School for Advanced Studies IUSS Pavia | | Earthquake Engineering PhD Candidate | | | |-----------------------------------------------------------------------| """ import numpy as np import openseespy.opensees as op import time import sys print('Extracting the mass matrix, ignore the following warnings...\n') op.wipeAnalysis() op.system('FullGeneral') op.analysis('Transient') # Extract the Mass Matrix op.integrator('GimmeMCK',1.0,0.0,0.0) op.analyze(1,0.0) time.sleep(0.5) # Number of equations in the model N = op.systemSize() # Has to be done after analyze Mmatrix = op.printA('-ret') # Or use op.printA('-file','M.out') Mmatrix = np.array(Mmatrix) # Convert the list to an array Mmatrix.shape = (N,N) # Make the array an NxN matrix print('\nExtracted the mass matrix, ignore the previous warnings...') # Rerrange the mass matrix in accordance with nodelist order from getNodeTags() DOFs = [] # These are the idx of all the DOFs used in the extract mass matrix, order is rearranged used = {} # Save here the nodes and their associated dofs used in global mass matrix lx = np.zeros([N,1]) # influence vector (x) ly = np.zeros([N,1]) # influence vector (y) lz = np.zeros([N,1]) # influence vector (z) lrx = np.zeros([N,1]) # influence vector (rx) lry = np.zeros([N,1]) # influence vector (ry) lrz = np.zeros([N,1]) # influence vector (rz) idx = 0 # index NDF = 6 # NDF is number of DOFs/node for node in op.getNodeTags(): used[node] = [] for j in range(NDF): temp = op.nodeDOFs(node)[j] if temp not in DOFs and temp >=0: DOFs.append(op.nodeDOFs(node)[j]) used[node].append(j+1) if j == 0: lx[idx,0] = 1 if j == 1: ly[idx,0] = 1 if j == 2: lz[idx,0] = 1 if j == 3: lrx[idx,0] = 1 if j == 4: lry[idx,0] = 1 if j == 5: lrz[idx,0] = 1 idx += 1 Mmatrix = Mmatrix[DOFs,:][:,DOFs] op.wipeAnalysis() listSolvers = ['-genBandArpack','-fullGenLapack','-symmBandLapack'] ok = 1 for s in listSolvers: print("Using %s as solver..." % s[1:]) try: eigenValues = op.eigen(s,numEigen) catchOK = 0 ok = 0 except: catchOK = 1 if catchOK==0: for i in range(numEigen): if eigenValues[i] < 0: ok = 1 if ok==0: print('Eigenvalue analysis is completed.') break if ok!=0: print("Error on Modal Analysis...") sys.exit() else: Lamda = np.asarray(eigenValues) Omega = Lamda**0.5 T = 2*np.pi/Omega f = 1/T print('Modal properties for the first %d modes:' % numEigen) Mx = []; My = []; Mz = []; Mrx = []; Mry = []; Mrz = [] dofs = ['x','y','z','rx','ry','rz'] print('Mode| T [sec] | f [Hz] | \u03C9 [rad/sec] | Mx [%] | My [%] | Mz [%] | \u2211Mx [%] | \u2211My [%] | \u2211Mz [%]') for mode in range(1,numEigen+1): # Although Mrx, Mry and Mrz are calculated, I am not printing these idx = 0 phi = np.zeros([N,1]) for node in used: for dof in used[node]: phi[idx,0]=op.nodeEigenvector(node,mode,dof) idx += 1 for dof in dofs: l = eval('l'+dof) Mtot = l.T@Mmatrix@l # Total mass in specified global dof Mn = phi.T@Mmatrix@phi # Modal mass in specified global dof Ln = phi.T@Mmatrix@l # Effective modal mass in specified global dof Mnstar = Ln**2/Mn/Mtot*100 # Normalised effective modal mass participating [%], in specified global dof eval('M'+dof).append(Mnstar[0,0]) # Save the modal mass for the specified dof print('%3s |%7s |%6s |%9s |%6s |%6s |%6s |%7s |%7s |%7s' \ % ("{:.0f}".format(mode), "{:.3f}".format(T[mode-1]), "{:.3f}".format(f[mode-1]), "{:.2f}".format(Omega[mode-1]), \ "{:.2f}".format(Mx[mode-1]), "{:.2f}".format(My[mode-1]), "{:.2f}".format(Mz[mode-1]), \ "{:.2f}".format(sum(Mx)), "{:.2f}".format(sum(My)), "{:.2f}".format(sum(Mz)))) Mtot = lx.T@Mmatrix@lx; Mtot = Mtot[0,0]
parttag = 1 ops.mesh('part', parttag, *partArgs, *eleArgs, '-vel', 0.0, 0.0) print('num particles =', nx * ny) # wall ops.node(1, 0.0, H) ops.node(2, 0.0, 0.0) ops.node(3, 4 * L, 0.0) ops.node(4, 4 * L, H) walltag = 2 wallid = 1 ops.mesh('line', walltag, 4, 1, 2, 3, 4, wallid, ndf, h) wallnodes = ops.getNodeTags('-mesh', walltag) for nd in wallnodes: ops.fix(nd, 1, 1) # background mesh lower = [-h, -h] upper = [4 * L + L, H + L] ops.mesh('bg', h, *lower, *upper, '-structure', wallid, len(wallnodes), *wallnodes) # create constraint object ops.constraints('Plain') # create numberer object
def RunAnalysis(): AnalysisType = 'Pushover' # Pushover Gravity ## ------------------------------ ## Start of model generation ## ----------------------------- # remove existing model ops.wipe() # set modelbuilder ops.model('basic', '-ndm', 2, '-ndf', 3) import math ############################################ ### Units and Constants ################### ############################################ inch = 1 kip = 1 sec = 1 # Dependent units sq_in = inch * inch ksi = kip / sq_in ft = 12 * inch # Constants g = 386.2 * inch / (sec * sec) pi = math.acos(-1) ####################################### ##### Dimensions ####################################### # Dimensions Input H_story = 10.0 * ft W_bayX = 16.0 * ft W_bayY_ab = 5.0 * ft + 10.0 * inch W_bayY_bc = 8.0 * ft + 4.0 * inch W_bayY_cd = 5.0 * ft + 10.0 * inch # Calculated dimensions W_structure = W_bayY_ab + W_bayY_bc + W_bayY_cd ################ ### Material ################ # Steel02 Material matTag = 1 matConnAx = 2 matConnRot = 3 Fy = 60.0 * ksi # Yield stress Es = 29000.0 * ksi # Modulus of Elasticity of Steel v = 0.2 # Poisson's ratio Gs = Es / (1 + v) # Shear modulus b = 0.10 # Strain hardening ratio params = [18.0, 0.925, 0.15] # R0,cR1,cR2 R0 = 18.0 cR1 = 0.925 cR2 = 0.15 a1 = 0.05 a2 = 1.00 a3 = 0.05 a4 = 1.0 sigInit = 0.0 alpha = 0.05 ops.uniaxialMaterial('Steel02', matTag, Fy, Es, b, R0, cR1, cR2, a1, a2, a3, a4, sigInit) # ################## # ## Sections # ################## colSecTag1 = 1 colSecTag2 = 2 beamSecTag1 = 3 beamSecTag2 = 4 beamSecTag3 = 5 # COMMAND: section('WFSection2d', secTag, matTag, d, tw, bf, tf, Nfw, Nff) ops.section('WFSection2d', colSecTag1, matTag, 10.5 * inch, 0.26 * inch, 5.77 * inch, 0.44 * inch, 15, 16) # outer Column ops.section('WFSection2d', colSecTag2, matTag, 10.5 * inch, 0.26 * inch, 5.77 * inch, 0.44 * inch, 15, 16) # Inner Column ops.section('WFSection2d', beamSecTag1, matTag, 8.3 * inch, 0.44 * inch, 8.11 * inch, 0.685 * inch, 15, 15) # outer Beam ops.section('WFSection2d', beamSecTag2, matTag, 8.2 * inch, 0.40 * inch, 8.01 * inch, 0.650 * inch, 15, 15) # Inner Beam ops.section('WFSection2d', beamSecTag3, matTag, 8.0 * inch, 0.40 * inch, 7.89 * inch, 0.600 * inch, 15, 15) # Inner Beam # Beam size - W10x26 Abeam = 7.61 * inch * inch IbeamY = 144. * (inch**4) # Inertia along horizontal axis IbeamZ = 14.1 * (inch**4) # inertia along vertical axis # BRB input data Acore = 2.25 * inch Aend = 10.0 * inch LR_BRB = 0.55 # ########################### # ##### Nodes # ########################### # Create All main nodes ops.node(1, 0.0, 0.0) ops.node(2, W_bayX, 0.0) ops.node(3, 2 * W_bayX, 0.0) ops.node(11, 0.0, H_story) ops.node(12, W_bayX, H_story) ops.node(13, 2 * W_bayX, H_story) ops.node(21, 0.0, 2 * H_story) ops.node(22, W_bayX, 2 * H_story) ops.node(23, 2 * W_bayX, 2 * H_story) ops.node(31, 0.0, 3 * H_story) ops.node(32, W_bayX, 3 * H_story) ops.node(33, 2 * W_bayX, 3 * H_story) # Beam Connection nodes ops.node(1101, 0.0, H_story) ops.node(1201, W_bayX, H_story) ops.node(1202, W_bayX, H_story) ops.node(1301, 2 * W_bayX, H_story) ops.node(2101, 0.0, 2 * H_story) ops.node(2201, W_bayX, 2 * H_story) ops.node(2202, W_bayX, 2 * H_story) ops.node(2301, 2 * W_bayX, 2 * H_story) ops.node(3101, 0.0, 3 * H_story) ops.node(3201, W_bayX, 3 * H_story) ops.node(3202, W_bayX, 3 * H_story) ops.node(3301, 2 * W_bayX, 3 * H_story) # ############### # Constraints # ############### ops.fix(1, 1, 1, 1) ops.fix(2, 1, 1, 1) ops.fix(3, 1, 1, 1) # ####################### # ### Elements # ####################### # ### Assign beam-integration tags ColIntTag1 = 1 ColIntTag2 = 2 BeamIntTag1 = 3 BeamIntTag2 = 4 BeamIntTag3 = 5 ops.beamIntegration('Lobatto', ColIntTag1, colSecTag1, 4) ops.beamIntegration('Lobatto', ColIntTag2, colSecTag2, 4) ops.beamIntegration('Lobatto', BeamIntTag1, beamSecTag1, 4) ops.beamIntegration('Lobatto', BeamIntTag2, beamSecTag2, 4) ops.beamIntegration('Lobatto', BeamIntTag3, beamSecTag3, 4) # Assign geometric transformation ColTransfTag = 1 BeamTranfTag = 2 ops.geomTransf('PDelta', ColTransfTag) ops.geomTransf('Linear', BeamTranfTag) # Assign Elements ############## # ## Add non-linear column elements ops.element('forceBeamColumn', 1, 1, 11, ColTransfTag, ColIntTag1, '-mass', 0.0) ops.element('forceBeamColumn', 2, 2, 12, ColTransfTag, ColIntTag2, '-mass', 0.0) ops.element('forceBeamColumn', 3, 3, 13, ColTransfTag, ColIntTag1, '-mass', 0.0) ops.element('forceBeamColumn', 11, 11, 21, ColTransfTag, ColIntTag1, '-mass', 0.0) ops.element('forceBeamColumn', 12, 12, 22, ColTransfTag, ColIntTag2, '-mass', 0.0) ops.element('forceBeamColumn', 13, 13, 23, ColTransfTag, ColIntTag1, '-mass', 0.0) ops.element('forceBeamColumn', 21, 21, 31, ColTransfTag, ColIntTag1, '-mass', 0.0) ops.element('forceBeamColumn', 22, 22, 32, ColTransfTag, ColIntTag2, '-mass', 0.0) ops.element('forceBeamColumn', 23, 23, 33, ColTransfTag, ColIntTag1, '-mass', 0.0) # ### Add linear main beam elements, along x-axis #element('elasticBeamColumn', 101, 1101, 1201, Abeam, Es, Gs, Jbeam, IbeamY, IbeamZ, beamTransfTag, '-mass', 0.0) ops.element('forceBeamColumn', 101, 1101, 1201, BeamTranfTag, BeamIntTag1, '-mass', 0.0) ops.element('forceBeamColumn', 102, 1202, 1301, BeamTranfTag, BeamIntTag1, '-mass', 0.0) ops.element('forceBeamColumn', 201, 2101, 2201, BeamTranfTag, BeamIntTag2, '-mass', 0.0) ops.element('forceBeamColumn', 202, 2202, 2301, BeamTranfTag, BeamIntTag2, '-mass', 0.0) ops.element('forceBeamColumn', 301, 3101, 3201, BeamTranfTag, BeamIntTag3, '-mass', 0.0) ops.element('forceBeamColumn', 302, 3202, 3301, BeamTranfTag, BeamIntTag3, '-mass', 0.0) # Assign constraints between beam end nodes and column nodes (RIgid beam column connections) ops.equalDOF(11, 1101, 1, 2, 3) ops.equalDOF(12, 1201, 1, 2, 3) ops.equalDOF(12, 1202, 1, 2, 3) ops.equalDOF(13, 1301, 1, 2, 3) ops.equalDOF(21, 2101, 1, 2, 3) ops.equalDOF(22, 2201, 1, 2, 3) ops.equalDOF(22, 2202, 1, 2, 3) ops.equalDOF(23, 2301, 1, 2, 3) ops.equalDOF(31, 3101, 1, 2, 3) ops.equalDOF(32, 3201, 1, 2, 3) ops.equalDOF(32, 3202, 1, 2, 3) ops.equalDOF(33, 3301, 1, 2, 3) AllNodes = ops.getNodeTags() massX = 0.49 for nodes in AllNodes: ops.mass(nodes, massX, massX, 0.00001) ################ ## Gravity Load ################ # create TimeSeries ops.timeSeries("Linear", 1) # create a plain load pattern ops.pattern("Plain", 1, 1) # Create the nodal load ops.load(11, 0.0, -5.0 * kip, 0.0) ops.load(12, 0.0, -6.0 * kip, 0.0) ops.load(13, 0.0, -5.0 * kip, 0.0) ops.load(21, 0., -5. * kip, 0.0) ops.load(22, 0., -6. * kip, 0.0) ops.load(23, 0., -5. * kip, 0.0) ops.load(31, 0., -5. * kip, 0.0) ops.load(32, 0., -6. * kip, 0.0) ops.load(33, 0., -5. * kip, 0.0) ############################### ### PUSHOVER ANALYSIS ############################### if (AnalysisType == "Pushover"): print("<<<< Running Pushover Analysis >>>>") # Create load pattern for pushover analysis # create a plain load pattern ops.pattern("Plain", 2, 1) ops.load(11, 1.61, 0.0, 0.0) ops.load(21, 3.22, 0.0, 0.0) ops.load(31, 4.83, 0.0, 0.0) ControlNode = 31 ControlDOF = 1 MaxDisp = 0.15 * H_story DispIncr = 0.1 NstepsPush = int(MaxDisp / DispIncr) Model = 'test' LoadCase = 'Pushover' dt = 0.2 opp.createODB(Model, LoadCase, Nmodes=3) ops.system("ProfileSPD") ops.numberer("Plain") ops.constraints("Plain") ops.integrator("DisplacementControl", ControlNode, ControlDOF, DispIncr) ops.algorithm("Newton") ops.test('NormUnbalance', 1e-8, 10) ops.analysis("Static") # analyze(NstepsPush) ops.analyze(100) print("Pushover analysis complete")
def get_node_coords(): node_coords = dict() node_tags = ops.getNodeTags() for i in node_tags: node_coords[i] = ops.nodeCoord(i) return node_coords
# wall mesh wall_tag = 3 ndf = 2 ops.mesh('line', 1, 9, 4,5,8,9,10,11,7,6,2, wall_id, ndf, h) ops.mesh('line', 2, 3, 2,1,4, wall_id, ndf, h) ops.mesh('tri', wall_tag, 2, 1,2, wall_id, ndf, h) # fluid mesh fluid_tag = 4 ops.mesh('line', 5, 3, 2,3,4, water_bound_id, ndf, h) eleArgs = ['PFEMElementBubble',rho,mu,b1,b2,thk,kappa] ops.mesh('tri', fluid_tag, 2, 2,5, water_body_id, ndf, h, *eleArgs) for nd in ops.getNodeTags('-mesh', wall_tag): ops.fix(nd, 1,1) # save the original modal ops.record() # create constraint object ops.constraints('Plain') # create numberer object ops.numberer('Plain') # create convergence test object ops.test('PFEM', 1e-5, 1e-5, 1e-5, 1e-5, 1e-15, 1e-15, 20, 3, 1, 2) # create algorithm object
def createOutputDatabase(self, Nmodes=0, deltaT=0.0, recorders=[]): """ This function creates a directory to save all the output data. Command: createODB("ModelName",<"LoadCase Name">, <Nmodes=Nmodes(int)>, <recorders=*recorder(list)>) ModelName : (string) Name of the model. The main output folder will be named "ModelName_ODB" in the current directory. LoadCase Name: (string), Optional. Name of the load case forder to be created inside the ModelName_ODB folder. If not provided, no load case data will be read. Nmodes : (int) Optional key argument to save modeshape data. Default is 0, no modeshape data is saved. deltaT : (float) Optional time interval for recording. will record when next step is deltaT greater than last recorder step. (default: records at every time step) recorders : (string) A list of additional quantities a users would like to record in the output database. The arguments for these additional inputs match the standard OpenSees arguments to avoid any confusion. 'localForce','basicDeformation', 'plasticDeformation','stresses','strains' The recorders for node displacement and reactions are saved by default to help plot the deformed shape. Example: createODB(TwoSpanBridge, Pushover, Nmodes=3, recorders=['stresses', 'strains']) Future: The integrationPoints output works only for nonlinear beam column elements. If a model has a combination of elastic and nonlienar elements, we need to create a method distinguish. """ ODBdir = self.ODBdir # ODB Dir name if not os.path.exists(ODBdir): os.makedirs(ODBdir) nodeList = op.getNodeTags() eleList = op.getEleTags() dofList = [int(ii + 1) for ii in range(len(op.nodeCoord(nodeList[0])))] # Save node and element data in the main Output folder self.saveNodesandElements() ######################### ## Create mode shape dir ######################### if Nmodes > 0: ModeShapeDir = os.path.join(ODBdir, "ModeShapes") if not os.path.exists(ModeShapeDir): os.makedirs(ModeShapeDir) ## Run eigen analysis internally and get information to print Tarray = np.zeros([1, Nmodes]) # To save all the periods of vibration op.wipeAnalysis() eigenVal = op.eigen(Nmodes + 1) for mm in range(1, Nmodes + 1): Tarray[0, mm - 1] = 4 * asin(1.0) / (eigenVal[mm - 1])**0.5 modeTFile = os.path.join(ModeShapeDir, "ModalPeriods.out") np.savetxt(modeTFile, Tarray, delimiter=self.delim, fmt=self.fmt) ### Save mode shape data for ii in range(1, Nmodes + 1): self.saveModeShapeData(ii) op.wipeAnalysis() LoadCaseDir = self.LoadCaseDir if not os.path.exists(LoadCaseDir): os.makedirs(LoadCaseDir) NodeDispFile = os.path.join(LoadCaseDir, "NodeDisp_All.out") EleForceFile = os.path.join(LoadCaseDir, "EleForce_All.out") ReactionFile = os.path.join(LoadCaseDir, "Reaction_All.out") EleStressFile = os.path.join(LoadCaseDir, "EleStress_All.out") EleStrainFile = os.path.join(LoadCaseDir, "EleStrain_All.out") EleBasicDefFile = os.path.join(LoadCaseDir, "EleBasicDef_All.out") ElePlasticDefFile = os.path.join(LoadCaseDir, "ElePlasticDef_All.out") # EleIntPointsFile = os.path.join(LoadCaseDir,"EleIntPoints_All.out") # Save recorders in the ODB folder op.recorder('Node', '-file', NodeDispFile, '-time', '-dT', deltaT, '-node', *nodeList, '-dof', *dofList, 'disp') op.recorder('Node', '-file', ReactionFile, '-time', '-dT', deltaT, '-node', *nodeList, '-dof', *dofList, 'reaction') if 'localForce' in recorders: op.recorder('Element', '-file', EleForceFile, '-time', '-dT', deltaT, '-ele', *eleList, '-dof', *dofList, 'localForce') if 'basicDeformation' in recorders: op.recorder('Element', '-file', EleBasicDefFile, '-time', '-dT', deltaT, '-ele', *eleList, '-dof', *dofList, 'basicDeformation') if 'plasticDeformation' in recorders: op.recorder('Element', '-file', ElePlasticDefFile, '-time', '-dT', deltaT, '-ele', *eleList, '-dof', *dofList, 'plasticDeformation') if 'stresses' in recorders: op.recorder('Element', '-file', EleStressFile, '-time', '-dT', deltaT, '-ele', *eleList, 'stresses') if 'strains' in recorders: op.recorder('Element', '-file', EleStrainFile, '-time', '-dT', deltaT, '-ele', *eleList, 'strains')
# section secTag = 1 ops.section('Elastic', secTag, E, A, Iz) # beam integration inteTag = 1 numpts = 2 ops.beamIntegration('Legendre', inteTag, secTag, numpts) # beam mesh beamTag = 6 ndf = 3 ops.mesh('line', beamTag, 2, 12, 13, beam_id, ndf, h, 'dispBeamColumn', transfTag, inteTag) ndmass = bmass / len(ops.getNodeTags('-mesh', beamTag)) for nd in ops.getNodeTags('-mesh', beamTag): ops.mass(nd, ndmass, ndmass, 0.0) # fluid mesh fluidTag = 4 ndf = 2 ops.mesh('line', 1, 10, 4, 5, 8, 9, 10, 11, 7, 6, 12, 2, wall_id, ndf, h) ops.mesh('line', 2, 3, 2, 1, 4, wall_id, ndf, h) ops.mesh('line', 3, 3, 2, 3, 4, water_bound_id, ndf, h) eleArgs = ['PFEMElementBubble', rho, mu, b1, b2, thk, kappa] ops.mesh('tri', fluidTag, 2, 2, 3, water_body_id, ndf, h, *eleArgs) # wall mesh
parttag = 1 ops.mesh('part', parttag, *partArgs, *eleArgs, '-vel', 0.0, 0.0) # wall mesh ops.node(1, 2 * L, 0.0) ops.node(2, 2 * L, Hb) ops.node(3, 0.0, H) ops.node(4, 0.0, 0.0) ops.node(5, 4 * L, 0.0) ops.node(6, 4 * L, H) sid = 1 walltag = 4 ops.mesh('line', walltag, 5, 3, 4, 1, 5, 6, sid, ndf, h) wallNodes = ops.getNodeTags('-mesh', walltag) for nd in wallNodes: ops.fix(nd, 1, 1, 1) # structural mesh # transformation transfTag = 1 ops.geomTransf('Corotational', transfTag) # section secTag = 1 if nonlinear: matTag = 1 ops.uniaxialMaterial('Steel01', matTag, Fy, E0, hardening) numfiber = 5