def RunPushoverAnalysis(Px,Py): # create TimeSeries op.timeSeries("Linear", 1) # create a plain load pattern op.pattern("Plain", 1, 1) # Create the nodal load - command: load nodeID xForce yForce op.load(4, Px, Py, 0.) # create SOE op.system("BandSPD") # create DOF number op.numberer("RCM") # create constraint handler op.constraints("Plain") # create integrator op.integrator("LoadControl", 1.0) # create algorithm op.algorithm("Newton") # create analysis object op.analysis("Static") # perform the analysis op.initialize() ok = op.analyze(1)
def analysis(P, du, steps, tol, max_iter): tsTag = 1 ops.timeSeries('Linear', tsTag) pattTag = 1 ops.pattern('Plain', pattTag, tsTag) ops.load(2, *P) ########################################################################## ops.constraints('Plain') ops.numberer('RCM') ops.system('BandGeneral') ops.test('NormUnbalance', tol, max_iter) ops.algorithm('Newton') ops.integrator('DisplacementControl', 2, 2, du, max_iter) ops.analysis('Static') ops.analyze(steps) ########################################################################## opsplt.plot_model() ########################################################################## ops.wipe()
def PDelta_analysis(Nnodes, P, steps, tol, max_iter): tsTag = 1 ops.timeSeries('Linear', tsTag) pattTag = 1 ops.pattern('Plain', pattTag, tsTag) ops.load(Nnodes, *P) ########################################################################## ops.constraints('Plain') ops.numberer('RCM') ops.system('BandGeneral') ops.test('NormUnbalance', tol, max_iter) ops.algorithm('Newton') temp = 1 / steps ops.integrator('LoadControl', temp) ops.analysis('Static') ops.analyze(steps) ########################################################################## opsplt.plot_model('nodes') ########################################################################## ops.wipe()
def PointLoad_analysis(Nnodes, P, tol, max_iter): tsTag = 10 ops.timeSeries('Linear', tsTag) pattTag = 10 ops.pattern('Plain', pattTag, tsTag) ops.load(Nnodes, *P) ########################################################################## ops.constraints('Plain') ops.numberer('RCM') ops.system('BandGeneral') ops.test('NormUnbalance', tol, max_iter) ops.algorithm('Newton') ops.integrator('LoadControl', 1) ops.analysis('Static') ops.analyze(1) ########################################################################## ops.wipe()
def run(arg_1, arg_2, arg_3, arg_4): ops.reset() ops.wipe() ops.model('basic', '-ndm', 3, '-ndf', 6) ops.node(1, 0.0, 0.0, 0.0) ops.node(2, 0.0, 3.2, 0.0) ops.fix(1, 1, 1, 1, 1, 1, 1) ops.uniaxialMaterial('Concrete01', 1, -80.0e6, -0.002, 0.0, -0.005) ops.section('Fiber', 1, '-GJ', 1) ops.patch('rect', 1, 10, 10, -0.8, -0.1, 0.8, 0.1) ops.geomTransf('Linear', 1, 0, 0, 1) ops.beamIntegration('Legendre', 1, 1, 10) ops.element('dispBeamColumn', 1, 1, 2, 1, 1) ops.timeSeries('Linear', 1) ops.pattern('Plain', 1, 1) ops.load(2, 0, -24586.24, 0, 0, 0, 0) ops.constraints('Plain') ops.numberer('RCM') ops.system('UmfPack') ops.test('NormDispIncr', 1.0e-6, 2000) ops.algorithm('Newton') ops.integrator('LoadControl', 0.01) ops.analysis('Static') ops.analyze(100) ops.wipeAnalysis() ops.loadConst('-time', 0.0) ops.recorder('Node', '-file', 'disp.out', ' -time', '-node', 2, '-dof', 1, 'disp') ops.recorder('Node', '-file', 'react.out', '-time ', '-node', 2, '-dof', 1, 'reaction') ops.timeSeries('Linear', 2) ops.pattern('Plain', 2, 2) ops.load(2, 11500, 0, 0, 0, 0, 0) ops.constraints('Plain') ops.numberer('RCM') ops.system('UmfPack') ops.test('NormDispIncr', 1.0, 2000) ops.algorithm('Newton') ops.integrator('LoadControl', 0.01) ops.analysis('Static') # ops.analyze(100) step = 100 data = np.zeros((step, 2)) for i in range(step): ops.analyze(1) data[i, 0] = ops.nodeDisp(2, 1) data[i, 1] = ops.getLoadFactor(2) * 11500 return data
def buildLinearAnalysis(gamma, beta): # do analysis ops.constraints('Plain') ops.numberer('Plain') ops.algorithm('Linear') ops.integrator('Newmark', gamma, beta) ops.system('ProfileSPD') ops.analysis('Transient')
def material_response(self, material, demand): """ Calculate the response of a material to a given load history. Parameters ---------- material: Material The material object to analyze. demand: DemandProtocol The load history the material shall be exposed to. Returns ------- response: DataFrame The DataFrame includes columns for strain (eps) and stress (sig). """ # initialize the analysis self._initialize() # define the structure struct = SDOF(Truss(material, l_tot=1., A_cs=1.)) struct.create_FEM(damping=False) id_ctrl_node = struct.ctrl_node load_dir = 1 # define the loading ops.timeSeries('Linear', 1) ops.pattern('Plain', 1, 1) if self.ndf == 1 and self.ndm == 1: ops.load(id_ctrl_node, 1.) # configure the analysis ops.constraints('Plain') ops.numberer('RCM') ops.system('UmfPack') ops.test('NormDispIncr', 1e-10, 100) ops.algorithm('NewtonLineSearch', '-maxIter', 100) # initialize the arrays for results result_size = demand.length response = pd.DataFrame(np.zeros((result_size + 1, 2)), columns=['eps', 'sig']) # perform the analysis for i, disp_incr in enumerate(demand.increments): ops.integrator('DisplacementControl', id_ctrl_node, load_dir, disp_incr) ops.analysis('Static') ops.analyze(1) response.loc[i + 1, 'eps'] = ops.nodeDisp(id_ctrl_node, load_dir) # response.loc[i+1, 'sig'] = ops.eleResponse(1, 'axialForce')[0] #![4] response.loc[i + 1, 'sig'] = ops.eleResponse(1, 'axialForce') #![4] return response
def PushoverLcD(dispMax): ControlNode = 4 ControlNodeDof = 1 du = 0.00002 * m # Define time series # timeSeries('Constant', tag, '-factor', factor=1.0) op.timeSeries('Constant', 1) op.timeSeries('Linear', 2) # define loads op.pattern('Plain', 1, 2) op.sp(ControlNode, ControlNodeDof, du) # Define Analysis Options # create SOE op.system("BandGeneral") # create DOF number op.numberer("Plain") # create constraint handler op.constraints("Transformation") # create integrator op.integrator("LoadControl", 1) # create algorithm op.algorithm("Newton") # create analysis object op.analysis("Static") # Create Test op.test('NormDispIncr', 1. * 10**-6, 50) # Run Analysis op.record() # ok = op.analyze(Nsteps) nn = 0 while (op.nodeDisp(ControlNode, ControlNodeDof) < dispMax): ok = op.analyze(1) if ok != 0: ok = BasicAnalysisLoop(ok, nn) if ok != 0: print("Analysis failed at load factor:", nn) break nn = +1 print() print("# Analysis Complete #")
def analysis_plain(): ''' analysis create ''' ops.constraints('Plain') ops.numberer('Plain') ops.system('BandGeneral') ops.test('EnergyIncr', 1.0e-6, 200) ops.algorithm('KrylovNewton') ops.integrator('DisplacementControl', 5, 3, -0.1) ops.analysis('Static') ops.analyze(100) logger.info("analysis created")
def analysis_rigid(): ''' for rigid ''' ops.constraints('Lagrange') ops.numberer('Plain') ops.system('BandGeneral') ops.test('EnergyIncr', 1.0e-6, 200) ops.algorithm('Newton') ops.integrator('LoadControl', 1e-2) ops.analysis('Static') ops.analyze(100) logger.info("analysis created")
def run_analysis(): # build the model ops.model('basic', '-ndm', 2, '-ndf', 2) ops.node(1, 0, 0) ops.node(2, 4000, 0) ops.node(3, 8000, 0) ops.node(4, 12000, 0) ops.node(5, 4000, 4000) ops.node(6, 8000, 4000) ops.fix(1, 1, 1) ops.fix(4, 0, 1) ops.uniaxialMaterial('Elastic', 1, E) ops.element('truss', 1, 1, 2, Ao, 1) ops.element('truss', 2, 2, 3, Ao, 1) ops.element('truss', 3, 3, 4, Ao, 1) ops.element('truss', 4, 1, 5, Au, 1) ops.element('truss', 5, 5, 6, Au, 1) ops.element('truss', 6, 6, 4, Au, 1) ops.element('truss', 7, 2, 5, Ao, 1) ops.element('truss', 8, 3, 6, Ao, 1) ops.element('truss', 9, 5, 3, Ao, 1) ops.timeSeries('Linear', 1) ops.pattern('Plain', 1, 1) ops.load(2, 0, -P) ops.load(3, 0, -P) # build and perform the analysis ops.algorithm('Linear') ops.integrator('LoadControl', 1.0) ops.system('ProfileSPD') ops.numberer('RCM') ops.constraints('Plain') ops.analysis('Static') ops.analyze(1) node_disp = [[ops.nodeDisp(node_i, dof_j) for dof_j in [1, 2]] for node_i in range(1, 7)] return node_disp
def analysis_plain_disp(test_tol=1.0e-3, test_iter=1000, nodeTag=0, dof=1, disp_incr=1, num_incr=10): ''' @analysis create in displacement control\n @default parameter: test_tol=1.0e-3, test_iter=1000, nodeTag=0, dof=1, disp_incr=1, num_incr=10 ''' logger.info("test_tol = %f, test_iter = %f, nodeTag = %d, dof = %d, disp_incr = %f, num_incr = %f", test_tol, test_iter, nodeTag, dof, disp_incr, num_incr) ops.constraints('Plain') ops.numberer('Plain') ops.system('BandGeneral') ops.test('EnergyIncr', test_tol, test_iter) ops.algorithm('KrylovNewton') ops.integrator('DisplacementControl', nodeTag, dof, disp_incr) ops.analysis('Static') ops.analyze(num_incr) logger.info("displacemen control analysis created")
def run_gravity_analysis(steps=10): """ Run gravity analysis (in 10 steps) """ ops.wipeAnalysis() ops.system("BandGeneral") ops.numberer("RCM") ops.constraints("Transformation") ops.test("NormDispIncr", 1.0E-12, 10, 3) ops.algorithm("Newton") # KrylovNewton ops.integrator("LoadControl", 1 / steps) ops.analysis("Static") ops.analyze(steps) title("Gravity Analysis Completed!") # Set the gravity loads to be constant & reset the time in the domain ops.loadConst("-time", 0.0) ops.wipeAnalysis()
def analysis_plain_load(test_tol=1.0e-12, test_iter=1000, incr=0.1, num_incr=11): ''' @analysis create in load control @default parameter: test_tol=1.0e-6, test_iter=1000, incr=0.1, num_incr=101 ''' logger.info("test_tol = %f, test_iter = %f, incr = %f, num_incr = %f", test_tol, test_iter, incr, num_incr) ops.constraints('Plain') ops.numberer('Plain') ops.system('BandGeneral') ops.test('EnergyIncr', test_tol, test_iter,) ops.algorithm('KrylovNewton') ops.integrator('LoadControl', incr) ops.analysis('Static') ops.analyze(num_incr) logger.info("load control analysis created")
def CyclicDisplace(Ddelta: float, Dnum: int, Dincr: float, Node: int, dof: int, tol: float, ite: float): ''' Ddelta: Displacement increment of each cyclic loading\n 每一个循环圈的位移增量\n Dnum: Number of cyclic loading times\n 循环的总圈数\n Dincr: Displacement increment in each analyze step\n 每一圈循环的增量步\n Node: Node which applied displacment\n dof: Direction of cyclic loading\n tol: the tolerance criteria used to check for convergence\n iter: the max number of iterations to check before returning failure condition\n u:Maxmini of cyclic displacment\n 每一圈循环的最大位移\n negdel: reverse of Dincr of cyclic increment step\n 每圈的反向增量步\n u/Dincr: number of direction cyclic step\n 一个方向的最大增量步步数\n 2 * u/Dincr: reverse direction cyclic step\n 反向加载的步数 因为要先回到远点再向负方向加载 ''' ops.constraints("Transformation") ops.numberer("RCM") ops.system("FullGeneral") ops.test('NormUnbalance', tol, ite, 0) ops.algorithm("Linear") for ii in range(1, Dnum + 1): u = Ddelta * ii negdel = -Dincr logger.info( "%d Cyclic of Displacement, node = %d, dof = %d , Dincr = %f Plus of Displacement...", ii, Node, dof, Dincr) Analysis_Proc(int(u / Dincr), Node, dof, Dincr) logger.info( "%d Cyclic of Displacement, node = %d, dof = %d, Dincr = %f Minus of Displacement...", ii, Node, dof, negdel) Analysis_Proc(int(2 * u / Dincr), Node, dof, negdel) logger.info( "%d Cyclic of Displacement, node = %d, dof = %d, Dincr = %f Back to Zero...", ii, Node, dof, Dincr) Analysis_Proc(int(u / Dincr), Node, dof, Dincr)
def MomentCurvature(secTag, axialLoad, maxK, numIncr=100): # Define two nodes at (0,0) ops.node(1, 0.0, 0.0) ops.node(2, 0.0, 0.0) # Fix all degrees of freedom except axial and bending ops.fix(1, 1, 1, 1) ops.fix(2, 0, 1, 0) # Define element # tag ndI ndJ secTag ops.element('zeroLengthSection', 1, 1, 2, secTag) # Define constant axial load ops.timeSeries('Constant', 1) ops.pattern('Plain', 1, 1) ops.load(2, axialLoad, 0.0, 0.0) # Define analysis parameters ops.integrator('LoadControl', 0.0) ops.system('SparseGeneral', '-piv') ops.test('NormUnbalance', 1e-9, 10) ops.numberer('Plain') ops.constraints('Plain') ops.algorithm('Newton') ops.analysis('Static') # Do one analysis for constant axial load ops.analyze(1) # Define reference moment ops.timeSeries('Linear', 2) ops.pattern('Plain', 2, 2) ops.load(2, 0.0, 0.0, 1.0) # Compute curvature increment dK = maxK / numIncr # Use displacement control at node 2 for section analysis ops.integrator('DisplacementControl', 2, 3, dK, 1, dK, dK) # Do the section analysis ops.analyze(numIncr)
def ops_gravity(): ops.recorder('Node', '-file', 'output\\gravity_disp.out', '-nodeRange', 651, 663, '-time', '-dof', 3, 'disp') ops.recorder('Node', '-file', 'output\\gravity_reaction.out', '-nodeRange', 651, 663, '-time', '-dof', 3, 'reaction') ops.timeSeries('Linear', 1) ops.pattern('Plain', 1, 1) load: float = [0, 0, (gravity_load + dead_load) / 13, 0, 0, 0] for i in range(651, 664): ops.load(i, *load) ops.constraints('Plain') ops.numberer('Plain') ops.system('BandGen') ops.test('NormDispIncr', 1.0, 1000) ops.algorithm('Newton') ops.integrator('LoadControl', 0.01) ops.analysis('Static') ok = ops.analyze(100) logger.info("gravity analyze result is %s", ok == 0)
def PushoverDcF(Nsteps): ControlNode = 4 ControlNodeDof = 1 dForce = 1.*kN du = 0.00001*m # Define time series # timeSeries('Constant', tag, '-factor', factor=1.0) op.timeSeries('Constant',1) op.timeSeries('Linear', 2) # define loads op.pattern('Plain',1 , 2) op.load(ControlNode, dForce, 0., 0.) # Define Analysis Options # create SOE op.system("BandGeneral") # create DOF number op.numberer("Plain") # create constraint handler op.constraints("Transformation") # create integrator op.integrator("DisplacementControl", ControlNode, ControlNodeDof, du) # create algorithm op.algorithm("Newton") # create analysis object op.analysis("Static") # Create Test op.test('NormDispIncr', 1.*10**-11, 50) # Run Analysis op.record() ok = op.analyze(Nsteps)
def add_nodes(joints_df, mass_df, list_new_joints, dict_of_hinges): # Identify the joints that were auto created by ETABS (like COM joints) points_df = joints_df[joints_df.IsAuto == 'Yes'].copy() # create joints in opensees mdoel joints_df.apply(lambda row: op.node(row.UniqueName, row.X, row.Y, row.Z), axis='columns') # add restraints to the joints joints_df.apply( lambda row: op.fix(row.UniqueName, *[int(r) for r in row.Restraints]), axis='columns') # special joint restraints for the COM joints points_df.apply(lambda row: op.fix(row.UniqueName, *[0, 0, 1, 1, 1, 0]), axis='columns') op.constraints('Transformation') # if the model diaphragm is rigid, define rigidity on each floor if rigid_dia: # obtain the list of floors in terms of the elevation (Z coordinate) floor_list = set(joints_df[joints_df.Z > joints_df.Z.min()].Z) # iterate through each floor to define rigid diaphragm for floor in floor_list: nodes_list = list( joints_df.loc[joints_df.Z == floor]['UniqueName']) remove_list = list(set(nodes_list) & set(list_new_joints)) + list( dict_of_hinges.keys()) nodes = [i for i in nodes_list if i not in remove_list] op.rigidDiaphragm(3, *nodes) # apply mass to the respective nodes mass_df.apply(lambda row: op.mass(row.PointElm, row.UX, row.UY, row.UZ, row .RX, row.RY, row.RZ), axis='columns') return
def analyse(self, num_incr): ''' Analyse the system. Args: num_incr: An integer number of load increments. return_node_disp: ''' ops.constraints('Transformation') ops.numberer('RCM') ops.system('BandGeneral') ops.test('NormUnbalance', 2e-8, num_incr) ops.algorithm('Newton') ops.integrator('LoadControl', 1 / num_incr) ops.record() ops.analysis('Static') ok = ops.analyze(num_incr) # Report analysis status if ok == 0: print("Analysis done.") else: print("Convergence issue.")
ops.element('elasticBeamColumn', 1, 1, 2, A, E, G, J, Iy, Iz, gTTagz) ops.element('elasticBeamColumn', 2, 2, 3, A, E, G, J, Iy, Iz, gTTagx) ops.element('elasticBeamColumn', 3, 3, 4, A, E, G, J, Iy, Iz, gTTagy) Ew = {} Px = -4.e1 Py = -2.5e1 Pz = -3.e1 ops.timeSeries('Constant', 1) ops.pattern('Plain', 1, 1) ops.load(4, Px, Py, Pz, 0., 0., 0.) ops.constraints('Transformation') ops.numberer('RCM') ops.system('BandGeneral') ops.test('NormDispIncr', 1.0e-6, 6, 2) ops.algorithm('Linear') ops.integrator('LoadControl', 1) ops.analysis('Static') ops.analyze(1) opsv.plot_model() sfac = 2.0e0 # fig_wi_he = 22., 14. fig_wi_he = 30., 20.
WzBeam = Weight / LBeam op.timeSeries('Linear', 1) op.pattern('Plain', 1, 1) op.eleLoad('-ele', 3, '-type', '-beamUniform', -WzBeam, 0.0, 0.0) #op.load(2, 0.0, -PCol, 0.0) Tol = 1e-8 # convergence tolerance for test NstepGravity = 10 DGravity = 1 / NstepGravity op.integrator('LoadControl', DGravity) # determine the next time step for an analysis op.numberer( 'Plain' ) # renumber dof's to minimize band-width (optimization), if you want to op.system('BandGeneral' ) # how to store and solve the system of equations in the analysis op.constraints('Plain') # how it handles boundary conditions op.test( 'NormDispIncr', Tol, 6 ) # determine if convergence has been achieved at the end of an iteration step op.algorithm( 'Newton' ) # use Newton's solution algorithm: updates tangent stiffness at every iteration op.analysis('Static') # define type of analysis static or transient op.analyze(NstepGravity) # apply gravity op.loadConst('-time', 0.0) #maintain constant gravity loads and reset time to zero print('Model Built')
def get_inelastic_response(fb, asig, extra_time=0.0, xi=0.05, analysis_dt=0.001): """ Run seismic analysis of a nonlinear FrameBuilding :param fb: FrameBuilding object :param asig: AccSignal object :param extra_time: float, additional analysis time after end of ground motion :param xi: damping ratio :param analysis_dt: time step to perform the analysis :return: """ op.wipe() op.model('basic', '-ndm', 2, '-ndf', 3) # 2 dimensions, 3 dof per node q_floor = 10000. # kPa trib_width = fb.floor_length trib_mass_per_length = q_floor * trib_width / 9.8 # Establish nodes and set mass based on trib area # Nodes named as: C<column-number>-S<storey-number>, first column starts at C1-S0 = ground level left nd = OrderedDict() col_xs = np.cumsum(fb.bay_lengths) col_xs = np.insert(col_xs, 0, 0) n_cols = len(col_xs) sto_ys = fb.heights sto_ys = np.insert(sto_ys, 0, 0) for cc in range(1, n_cols + 1): for ss in range(fb.n_storeys + 1): n_i = cc * 100 + ss nd["C%i-S%i" % (cc, ss)] = n_i op.node(n_i, col_xs[cc - 1], sto_ys[ss]) if ss != 0: if cc == 1: node_mass = trib_mass_per_length * fb.bay_lengths[0] / 2 elif cc == n_cols: node_mass = trib_mass_per_length * fb.bay_lengths[-1] / 2 else: node_mass = trib_mass_per_length * (fb.bay_lengths[cc - 2] + fb.bay_lengths[cc - 1] / 2) op.mass(n_i, node_mass) # Set all nodes on a storey to have the same displacement for ss in range(0, fb.n_storeys + 1): for cc in range(1, n_cols + 1): op.equalDOF(nd["C%i-S%i" % (1, ss)], nd["C%i-S%i" % (cc, ss)], opc.X) # Fix all base nodes for cc in range(1, n_cols + 1): op.fix(nd["C%i-S%i" % (cc, 0)], opc.FIXED, opc.FIXED, opc.FIXED) # Coordinate transformation geo_tag = 1 trans_args = [] op.geomTransf("Linear", geo_tag, *[]) l_hinge = fb.bay_lengths[0] * 0.1 # Define material e_conc = 30.0e6 i_beams = 0.4 * fb.beam_widths * fb.beam_depths ** 3 / 12 i_columns = 0.5 * fb.column_widths * fb.column_depths ** 3 / 12 a_beams = fb.beam_widths * fb.beam_depths a_columns = fb.column_widths * fb.column_depths ei_beams = e_conc * i_beams ei_columns = e_conc * i_columns eps_yield = 300.0e6 / 200e9 phi_y_col = calc_yield_curvature(fb.column_depths, eps_yield) phi_y_beam = calc_yield_curvature(fb.beam_depths, eps_yield) # Define beams and columns md = OrderedDict() # material dict sd = OrderedDict() # section dict ed = OrderedDict() # element dict # Columns named as: C<column-number>-S<storey-number>, first column starts at C1-S0 = ground floor left # Beams named as: B<bay-number>-S<storey-number>, first beam starts at B1-S1 = first storey left (foundation at S0) for ss in range(fb.n_storeys): # set columns for cc in range(1, fb.n_cols + 1): ele_i = cc * 100 + ss md["C%i-S%i" % (cc, ss)] = ele_i sd["C%i-S%i" % (cc, ss)] = ele_i ed["C%i-S%i" % (cc, ss)] = ele_i mat_props = elastic_bilin(ei_columns[ss][cc - 1], 0.05 * ei_columns[ss][cc - 1], phi_y_col[ss][cc - 1]) #print(opc.ELASTIC_BILIN, ele_i, *mat_props) op.uniaxialMaterial(opc.ELASTIC_BILIN, ele_i, *mat_props) # op.uniaxialMaterial("Elastic", ele_i, ei_columns[ss][cc - 1]) node_numbers = [nd["C%i-S%i" % (cc, ss)], nd["C%i-S%i" % (cc, ss + 1)]] op.element(opc.ELASTIC_BEAM_COLUMN, ele_i, *node_numbers, a_columns[ss - 1][cc - 1], e_conc, i_columns[ss - 1][cc - 1], geo_tag ) # Set beams for bb in range(1, fb.n_bays + 1): ele_i = bb * 10000 + ss md["B%i-S%i" % (bb, ss)] = ele_i sd["B%i-S%i" % (bb, ss)] = ele_i ed["B%i-S%i" % (bb, ss)] = ele_i mat_props = elastic_bilin(ei_beams[ss][bb - 1], 0.05 * ei_beams[ss][bb - 1], phi_y_beam[ss][bb - 1]) op.uniaxialMaterial(opc.ELASTIC_BILIN, ele_i, *mat_props) # op.uniaxialMaterial("Elastic", ele_i, ei_beams[ss][bb - 1]) node_numbers = [nd["C%i-S%i" % (bb, ss + 1)], nd["C%i-S%i" % (bb + 1, ss + 1)]] print((opc.BEAM_WITH_HINGES, ele_i, *node_numbers, sd["B%i-S%i" % (bb, ss)], l_hinge, sd["B%i-S%i" % (bb, ss)], l_hinge, sd["B%i-S%i" % (bb, ss)], geo_tag )) # Old definition # op.element(opc.BEAM_WITH_HINGES, ele_i, # *[nd["C%i-S%i" % (bb, ss - 1)], nd["C%i-S%i" % (bb + 1, ss)]], # sd["B%i-S%i" % (bb, ss)], l_hinge, # sd["B%i-S%i" % (bb, ss)], l_hinge, # e_conc, # a_beams[ss - 1][bb - 1], # i_beams[ss - 1][bb - 1], geo_tag # ) # New definition # op.element(opc.BEAM_WITH_HINGES, ele_i, # *node_numbers, # sd["B%i-S%i" % (bb, ss)], l_hinge, # sd["B%i-S%i" % (bb, ss)], l_hinge, # sd["B%i-S%i" % (bb, ss)], geo_tag # TODO: make this elastic # # ) # Elastic definition op.element(opc.ELASTIC_BEAM_COLUMN, ele_i, *node_numbers, a_beams[ss - 1][bb - 1], e_conc, i_beams[ss - 1][bb - 1], geo_tag ) # Define the dynamic analysis load_tag_dynamic = 1 pattern_tag_dynamic = 1 values = list(-1 * asig.values) # should be negative op.timeSeries('Path', load_tag_dynamic, '-dt', asig.dt, '-values', *values) op.pattern('UniformExcitation', pattern_tag_dynamic, opc.X, '-accel', load_tag_dynamic) # set damping based on first eigen mode angular_freq2 = op.eigen('-fullGenLapack', 1) if hasattr(angular_freq2, '__len__'): angular_freq2 = angular_freq2[0] angular_freq = angular_freq2 ** 0.5 if isinstance(angular_freq, complex): raise ValueError("Angular frequency is complex, issue with stiffness or mass") alpha_m = 0.0 beta_k = 2 * xi / angular_freq beta_k_comm = 0.0 beta_k_init = 0.0 period = angular_freq / 2 / np.pi print("period: ", period) op.rayleigh(alpha_m, beta_k, beta_k_init, beta_k_comm) # Run the dynamic analysis op.wipeAnalysis() op.algorithm('Newton') op.system('SparseGeneral') op.numberer('RCM') op.constraints('Transformation') op.integrator('Newmark', 0.5, 0.25) op.analysis('Transient') #op.test("NormDispIncr", 1.0e-1, 2, 0) tol = 1.0e-10 iter = 10 op.test('EnergyIncr', tol, iter, 0, 2) # TODO: make this test work analysis_time = (len(values) - 1) * asig.dt + extra_time outputs = { "time": [], "rel_disp": [], "rel_accel": [], "rel_vel": [], "force": [] } print("Analysis starting") while op.getTime() < analysis_time: curr_time = op.getTime() op.analyze(1, analysis_dt) outputs["time"].append(curr_time) outputs["rel_disp"].append(op.nodeDisp(nd["C%i-S%i" % (1, fb.n_storeys)], opc.X)) outputs["rel_vel"].append(op.nodeVel(nd["C%i-S%i" % (1, fb.n_storeys)], opc.X)) outputs["rel_accel"].append(op.nodeAccel(nd["C%i-S%i" % (1, fb.n_storeys)], opc.X)) op.reactions() react = 0 for cc in range(1, fb.n_cols): react += -op.nodeReaction(nd["C%i-S%i" % (cc, 0)], opc.X) outputs["force"].append(react) # Should be negative since diff node op.wipe() for item in outputs: outputs[item] = np.array(outputs[item]) return outputs
def get_pile_m(pile_z0=0, pile_z1=-30, pile_d=2, m0=7.5, pile_f=0, pile_m=0): 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) # 建立节点 node_z = np.linspace(pile_z0, pile_z1, elem_num + 1) for i, j in enumerate(node_z): ops.node(i + 1, 0, j) ops.node(i + 201, 0, j) # 约束 for i in range(len(node_z)): ops.fix(i + 1, 0, 1, 0) ops.fix(i + 201, 1, 1, 1) # 建立材料 ops.uniaxialMaterial('Elastic', 1, 3e4) 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', 100 + i, soil_k / 2) continue ops.uniaxialMaterial('Elastic', 100 + i, soil_k) # 装配 ops.geomTransf('Linear', 1) # 建立单元 for i in range(elem_num): ops.element('elasticBeamColumn', i + 1, i + 1, i + 2, pile_a, 3e10, pile_i, 1) # 建立弹簧 for i in range(len(node_z)): ops.element('zeroLength', i + 201, i + 1, i + 201, '-mat', 100 + i, '-dir', 1) ops.timeSeries('Linear', 1) ops.pattern('Plain', 1, 1) ops.load(1, pile_f, 0, pile_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 range(101): node_disp.append(ops.nodeDisp(i + 1)) node_disp = np.array(node_disp) * 1000 plt.figure() plt.subplot(121) for i, j in enumerate(node_z): if abs(node_disp[:, 0][i]) > max(abs(node_disp[:, 0])) / 50: if i == 0: plt.plot([0, node_disp[:, 0][i]], [j, j], linewidth=1.5, color='grey') else: plt.plot([0, node_disp[:, 0][i]], [j, j], linewidth=0.7, color='grey') if abs(node_disp[:, 0][i]) == max(abs(node_disp[:, 0])): plt.annotate(f'{node_disp[:, 0][i]:.1f} mm', xy=(node_disp[:, 0][i], j), xytext=(0.3, 0.5), textcoords='axes fraction', bbox=dict(boxstyle="round", fc="0.8"), arrowprops=dict(arrowstyle='->', connectionstyle="arc3,rad=-0.3")) plt.plot([0, 0], [node_z[0], node_z[-1]], linewidth=1.5, color='dimgray') plt.plot(node_disp[:, 0], node_z, linewidth=1.5, color='midnightblue') plt.xlabel('Displacement(mm)') plt.ylabel('Pile Depth(m)') # 绘制弯矩图 elem_m = [] for i in range(100): elem_m.append(ops.eleForce(i + 1)) elem_m = np.array(elem_m) / 1000 plt.subplot(122) for i, j in enumerate(node_z[:-1]): if abs(elem_m[:, 2][i]) > max(abs(elem_m[:, 2])) / 50: if i == 0: plt.plot([0, elem_m[:, 2][i]], [j, j], linewidth=1.5, color='grey') else: plt.plot([0, elem_m[:, 2][i]], [j, j], linewidth=0.7, color='grey') if abs(elem_m[:, 2][i]) == max(abs(elem_m[:, 2])): plt.annotate(f'{elem_m[:, 2][i]:.1f} kN.m', xy=(elem_m[:, 2][i], j), xytext=(0.5, 0.5), textcoords='axes fraction', bbox=dict(boxstyle="round", fc="0.8"), arrowprops=dict(arrowstyle='->', connectionstyle="arc3,rad=0.3")) plt.plot([0, 0], [node_z[0], node_z[-1]], linewidth=1.5, color='dimgray') plt.plot(elem_m[:, 2], node_z[:-1], linewidth=1.5, color='brown') plt.xlabel('Moment(kN.m)') # plt.ylabel('Pile Depth(m)') plt.show() return abs(max(elem_m[:, 2]))
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 NSProcedure(ndm, ndf, NbaysX, NbaysZ, NStr, XbayL, ZbayL, StoryH, lon, lat, SHL, Vso, gamma_soil, nu_soil, Re, fpc, Ec, gamma_conc, fy, E0, bsteel, ColTransfType, BeamEffFact, ColEffFact, g, Qsd, Ql, Qlr, EMs, R, Ie, StrType, BldTypCo, BldTypCm, DsgnType, dirs, directory): # The Nonlinear Static Procdure is executed in order to get responses # of a defined building. import openseespy.opensees as ops import OPSDefsMOD as OPSDMOD import OPSDefsAN as OPSDAN from timeit import default_timer as timer import ASCE716Seismic as ASCE716 import ASCE4117 import matplotlib.pyplot as plt import pickle import numpy as np for mm in range(len(NbaysX)): for nn in range(len(NStr)): for oo in range(len(Vso)): Teff = np.zeros( (len(dirs) )) # [s][LIST] effective lateral period of building. for ii in range(len(dirs)): time_o = timer() # Some previous definitions # ---------------------------- if DsgnType in ('conv_dsgn'): flex = 'no' elif DsgnType in ('ssi_dsgn'): flex = 'yes' # SiteClass = ASCE716.detSiteClass(Vso[oo]) # Unpicklin' some stored parameters from design process. # ------------------------------------------------------ workpath = directory + '\\RegularDesign\\' + str(NbaysX[mm])+'BayX'+str(NbaysZ)+\ 'BayZ'+str(NStr[nn])+'FLRS'+str(Vso[oo])+'.pickle' with open(workpath, 'rb') as f: ColDims, Colreinf, XBDims, XBreinf, ZBDims, ZBreinf, _, _, _, _, _, _, _, _, _, _ = pickle.load( f) # Calculation of height vector # ------------------------------ if flex in ('Y', 'YES', 'Yes', 'yES', 'yes', 'y'): # [m][LIST] with level height starting from first level or from base if foundation flexibility is included. hx = [0.0001] else: hx = [] for i in range(NStr[nn]): hx.append((i + 1) * StoryH) # Plan Dimensions of Building B = NbaysZ * ZbayL # [m] short side of building plan. L = NbaysX[mm] * XbayL # [m] long side of building plan. # Determination of MCEr spectral acceleration parameters # ------------------------------------------------------ (Sxs, Sx1) = ASCE4117.detSxi(lon, lat, Vso[oo], SHL) # MODELING OF THE STRUCTURE USING OPENSEESPY # =========================================== ops.wipe() OPSDMOD.ModelGen(ndm, ndf) OPSDMOD.NodeGen(NbaysX[mm], NbaysZ, XbayL, ZbayL, StoryH, NStr[nn], flex) OPSDMOD.MastNodeGen(NbaysX[mm], NbaysZ, XbayL, ZbayL, StoryH, NStr[nn], flex, coords=0) OPSDMOD.SPConstGen(NbaysX[mm], NbaysZ, flex) OPSDMOD.MPConstGen(NbaysX[mm], NbaysZ, NStr[nn], flex) OPSDMOD.MatGenRCB(fpc, Ec, fy, E0, bsteel) # OPSDMOD.GeomTransGen(ColTransfType,XBD=[min(XBDims[:,0]),min(XBDims[:,1])],\ # ZBD=[min(ZBDims[:,0]),min(ZBDims[:,1])],\ # ColD=[min(ColDims[:,0]),min(ColDims[:,1])]) OPSDMOD.GeomTransGen( ColTransfType, ColD=[min(ColDims[:, 0]), min(ColDims[:, 1])]) # OPSDMOD.GeomTransGen(ColTransfType) if flex in ('Y', 'YES', 'Yes', 'yES', 'yes', 'y'): # Interface elements generation for foundation flexibility considerations. # ========================================================================= # Materials generation: stiffness constants accounting for soil flexibility. # --------------------------------------------------------------------------- OPSDMOD.FoundFlexMaterials(NbaysX[mm],NbaysZ,XbayL,ZbayL,Sxs,Vso[oo],gamma_soil,nu_soil,B,L,Re,\ D=0,omega_soil=0,analtype='lat') # Zero-Length elements creation for connecting base nodes. OPSDMOD.FoundFlexZLElements(NbaysX[mm], NbaysZ, XbayL, ZbayL, B, L, Re) OPSDMOD.ElementGen(NbaysX[mm],NbaysZ,XbayL,ZbayL,NStr[nn],StoryH,XBDims,ZBDims,\ ColDims,BeamEffFact,ColEffFact,Ec,fy,EMs,\ XBreinf,ZBreinf,Colreinf,N=5,rec=0.0654,nuconc=0.2,dbar=0.025) [Wx,MassInputMatr] = \ OPSDMOD.LumpedMassGen(NbaysX[mm],NbaysZ,XBDims,ZBDims,ColDims,gamma_conc,g,XbayL,ZbayL,NStr[nn],StoryH,Qsd,flex) W = sum(Wx) # [kN] total weight of the building # GRAVITY LOADS APPLIED TO MODEL ACCORDINGO TO ASCE4117 # ====================================================== # According to ASCE4117 Section 7.2.2, equation (7-3), the combination # of gravitational loads mus be as follows: # Qg = Qd + 0.25*Ql + Qs (7-3) OPSDMOD.DeadLoadGen(NbaysX[mm], NbaysZ, NStr[nn], XBDims, ZBDims, ColDims, gamma_conc) OPSDMOD.SuperDeadLoadGen(NbaysX[mm], NbaysZ, NStr[nn], XbayL, ZbayL, Qsd) OPSDMOD.LiveLoadGen(NbaysX[mm], NbaysZ, NStr[nn], XbayL, ZbayL, 0.25 * Ql, 0.25 * Qlr) # GRAVITY-LOADS-CASE ANALYSIS. # ============================ ops.system('ProfileSPD') ops.constraints('Transformation') ops.numberer('RCM') ops.test('NormDispIncr', 1.0e-4, 100) ops.algorithm('KrylovNewton') ops.integrator('LoadControl', 1) ops.analysis('Static') ops.analyze(1) # Vertical reactions Calculation for verification. # ------------------------------------------------ ops.reactions() YReact = 0 for i in range((NbaysX[mm] + 1) * (NbaysZ + 1)): if flex in ('Y', 'YES', 'Yes', 'yES', 'yes', 'y'): YReact += ops.nodeReaction(int(i + 1), 2) else: YReact += ops.nodeReaction(int(i + 1 + 1e4), 2) # ========================================================================== # MODAL ANALYSIS FOR DETERMINING FUNDAMENTAL PERIOD AND ITS DIRECTION. # ========================================================================== (T, Tmaxver, Mast) = OPSDAN.ModalAnalysis(NStr[nn], B, L, Wx, flex) print(T) # ================== # PUSHOVER ANALYSIS # ================== # Lateral Force used for analysis # -------------------------------- # Using functions from ASCE716Seismic Module. (_,_,_,_,_,_,_,_,_,_,_,FxF,_,_,_) = \ ASCE716.ELFP(Sxs,Sx1,Vso[oo],Wx,R,Ie,hx,StrType,T[0,ii]) # Aplication of forces to the model. # ---------------------------------- ops.loadConst('-time', 0.0) MdeShape = OPSDMOD.POForceGen(NStr[nn], FxF, dirs[ii], flex) # ============================================= # First Execution of the analysis and output results. # ============================================= (results1,dtg1,tgfactor1) = \ OPSDAN.POAnalysisProc(lon,lat,Vso[oo],SHL,NbaysX[mm],NbaysZ,\ NStr[nn],StoryH,R,Ie,BldTypCo,BldTypCm,\ T[0,ii],W,dirs[ii],flex,\ DispIncr=0,beta=0.05,TL=8.,Tf=6.0,Npts=500,Vy=0,Te=0) # [Disp,Force] # ===================================================== # Determining the first approximation of values of Vy # and calculation of effective fundamental period for NSP # ===================================================== (Delta_y, V_y, Delta_d, V_d, Ke, alpha1, alpha2) = \ ASCE4117.IFDC(dtg1,results1) Ki = Mast[ii] * 4 * np.pi**2 / T[ 0, ii]**2 # [kN/m] elastic lateral stiffness of the building. Teff[ii] = T[0, ii] * ( Ki / Ke )**0.5 # [s] effctive fundamental period of building. # ============================================= # Second Execution of the analysis and output results. # ============================================= ops.wipe() OPSDMOD.ModelGen(ndm, ndf) OPSDMOD.NodeGen(NbaysX[mm], NbaysZ, XbayL, ZbayL, StoryH, NStr[nn], flex) OPSDMOD.MastNodeGen(NbaysX[mm], NbaysZ, XbayL, ZbayL, StoryH, NStr[nn], flex, coords=0) OPSDMOD.SPConstGen(NbaysX[mm], NbaysZ, flex) OPSDMOD.MPConstGen(NbaysX[mm], NbaysZ, NStr[nn], flex) OPSDMOD.MatGenRCB(fpc, Ec, fy, E0, bsteel) # OPSDMOD.GeomTransGen(ColTransfType,XBD=[min(XBDims[:,0]),min(XBDims[:,1])],\ # ZBD=[min(ZBDims[:,0]),min(ZBDims[:,1])],\ # ColD=[min(ColDims[:,0]),min(ColDims[:,1])]) OPSDMOD.GeomTransGen( ColTransfType, ColD=[min(ColDims[:, 0]), min(ColDims[:, 1])]) # OPSDMOD.GeomTransGen(ColTransfType) if flex in ('Y', 'YES', 'Yes', 'yES', 'yes', 'y'): # Interface elements generation for foundation flexibility considerations. # ========================================================================= # Materials generation: stiffness constants accounting for soil flexibility. # --------------------------------------------------------------------------- OPSDMOD.FoundFlexMaterials(NbaysX[mm],NbaysZ,XbayL,ZbayL,Sxs,Vso[oo],gamma_soil,nu_soil,B,L,Re,\ D=0,omega_soil=0,analtype='lat') # Zero-Length elements creation for connecting base nodes. OPSDMOD.FoundFlexZLElements(NbaysX[mm], NbaysZ, XbayL, ZbayL, B, L, Re) OPSDMOD.ElementGen(NbaysX[mm],NbaysZ,XbayL,ZbayL,NStr[nn],StoryH,XBDims,ZBDims,\ ColDims,BeamEffFact,ColEffFact,Ec,fy,EMs,\ XBreinf,ZBreinf,Colreinf,N=5,rec=0.0654,nuconc=0.2,dbar=0.025) [Wx,MassInputMatr] = \ OPSDMOD.LumpedMassGen(NbaysX[mm],NbaysZ,XBDims,ZBDims,ColDims,gamma_conc,g,XbayL,ZbayL,NStr[nn],StoryH,Qsd,flex) W = sum(Wx) # [kN] total weight of the building # GRAVITY LOADS APPLIED TO MODEL ACCORDINGO TO ASCE4117 # ====================================================== OPSDMOD.DeadLoadGen(NbaysX[mm], NbaysZ, NStr[nn], XBDims, ZBDims, ColDims, gamma_conc) OPSDMOD.SuperDeadLoadGen(NbaysX[mm], NbaysZ, NStr[nn], XbayL, ZbayL, Qsd) OPSDMOD.LiveLoadGen(NbaysX[mm], NbaysZ, NStr[nn], XbayL, ZbayL, 0.25 * Ql, 0.25 * Qlr) # GRAVITY-LOADS-CASE ANALYSIS. # ============================ ops.system('ProfileSPD') ops.constraints('Transformation') ops.numberer('RCM') ops.test('NormDispIncr', 1.0e-4, 100) ops.algorithm('KrylovNewton') ops.integrator('LoadControl', 1) ops.analysis('Static') ops.analyze(1) # ================== # PUSHOVER ANALYSIS # ================== # Lateral Force used for analysis # -------------------------------- # Using functions from ASCE716Seismic Module. (_,_,_,_,_,_,_,_,_,_,_,FxF,_,_,_) = \ ASCE716.ELFP(Sxs,Sx1,Vso[oo],Wx,R,Ie,hx,StrType,Teff[ii]) # Aplication of forces to the model. # ---------------------------------- ops.loadConst('-time', 0.0) MdeShape = OPSDMOD.POForceGen(NStr[nn], FxF, dirs[ii], flex) # ============================================= # First Execution of the analysis and output results. # ============================================= (results2,dtg2,tgfactor2) = \ OPSDAN.POAnalysisProc(lon,lat,Vso[oo],SHL,NbaysX[mm],NbaysZ,\ NStr[nn],StoryH,R,Ie,BldTypCo,BldTypCm,\ T[0,ii],W,dirs[ii],flex,\ DispIncr=0,beta=0.05,TL=8.,Tf=6.0,Npts=500,Vy=0,Te=Teff[ii]) # [Disp,Force]. # ===================================================== # Determining the "exact" values of Vy # and calculation of effective fundamental period for NSP # ===================================================== (Delta_y, V_y, Delta_d, V_d, Ke, alpha1, alpha2) = \ ASCE4117.IFDC(dtg1,results2) Ki = Mast[ii] * 4 * np.pi**2 / T[ 0, ii]**2 # [kN/m] elastic lateral stiffness of the building. Teff[ii] = T[0, ii] * ( Ki / Ke )**0.5 # [s] effctive fundamental period of building. ttime = timer() - time_o print(f'Elapsed Time {round(ttime/60,2)} [m]') plt.figure() plt.plot(results2[:, 0], results2[:, 1]) plt.grid() print('The mode shape is:') print(MdeShape) return (results1, results2), (dtg1, dtg2), (tgfactor1, tgfactor2), (tgfactor1 * dtg1, tgfactor2 * dtg2)
def __init__(self): # AIが取れるアクションの設定 self.action = np.array([ 0, 0.02, 0.03, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1 ]) self.naction = len(self.action) self.beta = 1 / 4 # 1質点系モデル self.T0 = 4 self.h = self.action[0] self.hs = [self.h] self.m = 100 self.k = 4 * np.pi**2 * self.m / self.T0**2 # 入力地震動 self.dt = 0.02 to_meter = 0.01 # cmをmに変換する値 self.wave_url = 'https://github.com/kakemotokeita/dqn-seismic-control/blob/master/wave/sample.csv' with urllib.request.urlopen(self.wave_url) as wave_file: self.wave_data = np.loadtxt( wave_file, usecols=(0, ), delimiter=',', skiprows=3) * to_meter # OpenSees設定 op.wipe() op.model('basic', '-ndm', 2, '-ndf', 3) # 2 dimensions, 3 dof per node # 節点 self.bot_node = 1 self.top_node = 2 op.node(self.bot_node, 0., 0.) op.node(self.top_node, 0., 0.) # 境界条件 op.fix(self.top_node, FREE, FIXED, FIXED) op.fix(self.bot_node, FIXED, FIXED, FIXED) op.equalDOF(1, 2, *[Y, ROTZ]) # 質量 op.mass(self.top_node, self.m, 0., 0.) # 弾性剛性 elastic_mat_tag = 1 Fy = 1e10 E0 = self.k b = 1.0 op.uniaxialMaterial('Steel01', elastic_mat_tag, Fy, E0, b) # Assign zero length element beam_tag = 1 op.element('zeroLength', beam_tag, self.bot_node, self.top_node, "-mat", elastic_mat_tag, "-dir", 1, '-doRayleigh', 1) # Define the dynamic analysis load_tag_dynamic = 1 pattern_tag_dynamic = 1 self.values = list(-1 * self.wave_data) # should be negative op.timeSeries('Path', load_tag_dynamic, '-dt', self.dt, '-values', *self.values) op.pattern('UniformExcitation', pattern_tag_dynamic, X, '-accel', load_tag_dynamic) # 減衰の設定 self.w0 = op.eigen('-fullGenLapack', 1)[0]**0.5 self.alpha_m = 0.0 self.beta_k = 2 * self.h / self.w0 self.beta_k_init = 0.0 self.beta_k_comm = 0.0 op.rayleigh(self.alpha_m, self.beta_k, self.beta_k_init, self.beta_k_comm) # Run the dynamic analysis op.wipeAnalysis() op.algorithm('Newton') op.system('SparseGeneral') op.numberer('RCM') op.constraints('Transformation') op.integrator('Newmark', 0.5, 0.25) op.analysis('Transient') tol = 1.0e-10 iterations = 10 op.test('EnergyIncr', tol, iterations, 0, 2) self.i_pre = 0 self.i = 0 self.i_next = 0 self.time = 0 self.analysis_time = (len(self.values) - 1) * self.dt self.dis = 0 self.vel = 0 self.acc = 0 self.a_acc = 0 self.force = 0 self.resp = { "time": [], "dis": [], "acc": [], "a_acc": [], "vel": [], "force": [], } self.done = False
def analisis_opensees(path, permutaciones): #helper, #win ops.wipe() # bucle para generar los x análisis for i in range(len(permutaciones)): perfil = str(permutaciones[i][0]) nf = permutaciones[i][2] amort = permutaciones[i][3] den = permutaciones[i][4] vel = permutaciones[i][5] capas = len(permutaciones[i][6]) nstep = permutaciones[i][30] dt = float(permutaciones[i][31]) # creación de elementos sElemX = permutaciones[i][1] # elementos en X sElemZ = permutaciones[i][46] # espesor en Z # ============================================================================= # ######## geometría de la columna ###### # ============================================================================= # límite entre capas limite_capa = [] anterior = 0 for j in range(capas): espesor = permutaciones[i][8][j] limite_capa.append(espesor + anterior) anterior = limite_capa[j] print('Límite de capa: ' + str(limite_capa[j])) # creación de elementos y nodos en x nElemX = 1 # elementos en x nNodeX = 2 * nElemX + 1 # nodos en x # creación de elementos y nodos para z nElemZ = 1 # creación de elementos y nodos en Y y totales nElemY = [] # elementos en y sElemY = [] # dimension en y nElemT = 0 for j in range(capas): espesor = permutaciones[i][8][j] nElemY.append(2 * espesor) nElemT += nElemY[j] print('Elementos en capa ' + str(j + 1) + ': ' + str(nElemY[j])) sElemY.append(permutaciones[i][8][j] / nElemY[j]) print('Tamaño de los elementos en capa ' + str(j + 1) + ': ' + str(sElemY[j]) + '\n') # number of nodes in vertical direction in each layer nNodeY = [] # dimension en y nNodeT = 0 s = 0 for j in range(capas - 1): nNodeY.append(4 * nElemY[j]) nNodeT += nNodeY[j] s += 1 print('Nodos en capa ' + str(j + 1) + ': ' + str(nNodeY[j])) nNodeY.append(4 * (nElemY[-1] + 1)) nNodeT += nNodeY[-1] print('Nodos en capa ' + str(s + 1) + ': ' + str(nNodeY[s])) print('Nodos totales: ' + str(nNodeT)) #win.ui.progressBar.setValue(15) # ============================================================================= # ######### Crear nodos del suelo ########## # ============================================================================= # creación de nodos de presión de poros ops.model('basic', '-ndm', 3, '-ndf', 4) with open(path + '/Post-proceso/' + perfil + '/ppNodesInfo.dat', 'w') as f: count = 0.0 yCoord = 0.0 nodos = [] dryNode = [] altura_nf = 10 - nf for k in range(capas): for j in range(0, int(nNodeY[k]), 4): ops.node(j + count + 1, 0.0, yCoord, 0.0) ops.node(j + count + 2, 0.0, yCoord, sElemZ) ops.node(j + count + 3, sElemX, yCoord, sElemZ) ops.node(j + count + 4, sElemX, yCoord, 0.0) f.write( str(int(j + count + 1)) + '\t' + str(0.0) + '\t' + str(yCoord) + '\t' + str(0.0) + '\n') f.write( str(int(j + count + 2)) + '\t' + str(0.0) + '\t' + str(yCoord) + '\t' + str(sElemZ) + '\n') f.write( str(int(j + count + 3)) + '\t' + str(sElemX) + '\t' + str(yCoord) + '\t' + str(sElemZ) + '\n') f.write( str(int(j + count + 4)) + '\t' + str(sElemX) + '\t' + str(yCoord) + '\t' + str(0.0) + '\n') nodos.append(str(j + count + 1)) nodos.append(str(j + count + 2)) nodos.append(str(j + count + 3)) nodos.append(str(j + count + 4)) #designate node sobre la superficie de agua if yCoord >= altura_nf: dryNode.append(j + count + 1) dryNode.append(j + count + 2) dryNode.append(j + count + 3) dryNode.append(j + count + 4) yCoord = (yCoord + sElemY[k]) count = (count + nNodeY[k]) print("Finished creating all soil nodes...") # ============================================================================= # ####### Condiciones de contorno en la base de la columna ######### # ============================================================================= ops.fix(1, *[0, 1, 1, 0]) ops.fix(2, *[0, 1, 1, 0]) ops.fix(3, *[0, 1, 1, 0]) ops.fix(4, *[0, 1, 1, 0]) ops.equalDOF(1, 2, 1) ops.equalDOF(1, 3, 1) ops.equalDOF(1, 4, 1) print('Fin de creación de nodos de la base de la columna\n\n') # ============================================================================= # ####### Condiciones de contorno en los nudos restantes ######### # ============================================================================= count = 0 for k in range(5, int(nNodeT + 1), 4): ops.equalDOF(k, k + 1, *[1, 2, 3]) ops.equalDOF(k, k + 2, *[1, 2, 3]) ops.equalDOF(k, k + 3, *[1, 2, 3]) print('Fin de creación equalDOF para nodos de presión de poros\n\n') for j in range(len(dryNode)): ops.fix(dryNode[j], *[0, 0, 0, 1]) print("Finished creating all soil boundary conditions...") # ============================================================================= # ####### crear elemento y material de suelo ######### # ============================================================================= cargas = [] for j in range(capas): pendiente = permutaciones[i][9][j] slope = math.atan(pendiente / 100) tipo_suelo = permutaciones[i][6][j] rho = permutaciones[i][10][j] Gr = permutaciones[i][12][j] Br = permutaciones[i][13][j] fric = permutaciones[i][15][j] refpress = permutaciones[i][18][j] gmax = permutaciones[i][19][j] presscoef = permutaciones[i][20][j] surf = permutaciones[i][21][j] ev = permutaciones[i][22][j] cc1 = permutaciones[i][23][j] cc3 = permutaciones[i][24][j] cd1 = permutaciones[i][25][j] cd3 = permutaciones[i][26][j] ptang = permutaciones[i][27][j] coh = permutaciones[i][28][j] if tipo_suelo == 'No cohesivo': if float(surf) > 0: ops.nDMaterial('PressureDependMultiYield02', j + 1, 3.0, rho, Gr, Br, fric, gmax, refpress, presscoef, ptang, cc1, cc3, cd1, cd3, float(surf), 5.0, 3.0, *[1.0, 0.0], ev, *[0.9, 0.02, 0.7, 101.0]) else: ops.nDMaterial('PressureDependMultiYield02', j + 1, 3.0, rho, Gr, Br, fric, gmax, refpress, presscoef, ptang, cc1, cc3, cd1, cd3, float(surf), *permutaciones[i][29][j], 5.0, 3.0, *[1.0, 0.0], ev, *[0.9, 0.02, 0.7, 101.0]) cargas.append( [0.0, -9.81 * math.cos(slope), -9.81 * math.sin(slope)]) print('Fin de la creación de material de suelo\n\n') #----------------------------------------------------------------------------------------- # 5. CREATE SOIL ELEMENTS #----------------------------------------------------------------------------------------- count = 0 alpha = 1.5e-6 with open(path + '/Post-proceso/' + perfil + '/ppElemInfo.dat', 'w') as f: # crear elemento de suelo for k in range(capas): for j in range(int(nElemY[k])): nI = 4 * (j + count + 1) - 3 nJ = nI + 1 nK = nI + 2 nL = nI + 3 nM = nI + 4 nN = nI + 5 nO = nI + 6 nP = nI + 7 f.write( str(j + count + 1) + '\t' + str(nI) + '\t' + str(nJ) + '\t' + str(nK) + '\t' + str(nL) + '\t' + str(nM) + '\t' + str(nN) + '\t' + str(nO) + '\t' + str(nP) + '\n') Bc = permutaciones[i][14][k] ev = permutaciones[i][22][k] ops.element('SSPbrickUP', (j + count + 1), *[nI, nJ, nK, nL, nM, nN, nO, nP], (k + 1), float(Bc), 1.0, 1.0, 1.0, 1.0, float(ev), alpha, cargas[k][0], cargas[k][1], cargas[k][2]) count = (count + int(nElemY[k])) print('Fin de la creación del elemento del suelo\n\n') #win.ui.progressBar.setValue(25) # ============================================================================= # ######### Amortiguamiento de Lysmer ########## # ============================================================================= ops.model('basic', '-ndm', 3, '-ndf', 3) # definir nodos y coordenadas del amortiguamiento dashF = nNodeT + 1 dashX = nNodeT + 2 dashZ = nNodeT + 3 ops.node(dashF, 0.0, 0.0, 0.0) ops.node(dashX, 0.0, 0.0, 0.0) ops.node(dashZ, 0.0, 0.0, 0.0) # definir restricciones para los nodos de amortiguamiento ops.fix(dashF, 1, 1, 1) ops.fix(dashX, 0, 1, 1) ops.fix(dashZ, 1, 1, 0) # definir equalDOF para el amortiguamiento en la base del suelo ops.equalDOF(1, dashX, 1) ops.equalDOF(1, dashZ, 3) print( 'Fin de la creación de condiciones de contorno de los nodos de amortiguamiento\n\n' ) # definir el material de amortiguamiento colArea = sElemX * sElemZ dashpotCoeff = vel * den * colArea ops.uniaxialMaterial('Viscous', capas + 1, dashpotCoeff, 1.0) # definir el elemento ops.element('zeroLength', nElemT + 1, *[dashF, dashX], '-mat', capas + 1, '-dir', *[1]) ops.element('zeroLength', nElemT + 2, *[dashF, dashZ], '-mat', capas + 1, '-dir', *[3]) print('Fin de la creación del elemento de amortiguamiento\n\n') #----------------------------------------------------------------------------------------- # 9. DEFINE ANALYSIS PARAMETERS #----------------------------------------------------------------------------------------- # amortiguamiento de Rayleigh # frecuencia menor omega1 = 2 * math.pi * 0.2 # frecuencia mayor omega2 = 2 * math.pi * 20 a0 = 2.0 * (amort / 100) * omega1 * omega2 / (omega1 + omega2) a1 = 2.0 * (amort / 100) / (omega1 + omega2) print('Coeficientes de amortiguamiento' + '\n' + 'a0: ' + format(a0, '.6f') + '\n' + 'a1: ' + format(a1, '.6f') + '\n\n') #win.ui.progressBar.setValue(35) # ============================================================================= # ######## Determinación de análisis estático ######### # ============================================================================= #---DETERMINE STABLE ANALYSIS TIME STEP USING CFL CONDITION # se determina a partir de un análisis transitorio de largo tiempo duration = nstep * dt # tamaño mínimo del elemento y velocidad máxima minSize = sElemY[0] vsMax = permutaciones[i][11][0] for j in range(1, capas): if sElemY[j] < minSize: minSize = sElemY[j] if permutaciones[i][11][j] > vsMax: vsMax = permutaciones[i][11][j] # trial analysis time step kTrial = minSize / (vsMax**0.5) # tiempo de análisis y pasos de tiempo if dt <= kTrial: nStep = nstep dT = dt else: nStep = int(math.floor(duration / kTrial) + 1) dT = duration / nStep print('Número de pasos en el análisis: ' + str(nStep) + '\n') print('Incremento de tiempo: ' + str(dT) + '\n\n') #---------------------------------------------------------------------------------------- # 7. GRAVITY ANALYSIS #----------------------------------------------------------------------------------------- ops.model('basic', '-ndm', 3, '-ndf', 4) ops.updateMaterialStage('-material', int(k + 1), '-stage', 0) # algoritmo de análisis estático ops.constraints(permutaciones[i][32][0], float(permutaciones[i][32][1]), float(permutaciones[i][32][2])) ops.test(permutaciones[i][34][0], float(permutaciones[i][34][1]), int(permutaciones[i][34][2]), int(permutaciones[i][34][3])) ops.algorithm(permutaciones[i][38][0]) ops.numberer(permutaciones[i][33][0]) ops.system(permutaciones[i][36][0]) ops.integrator(permutaciones[i][35][0], float(permutaciones[i][35][1]), float(permutaciones[i][35][2])) ops.analysis(permutaciones[i][37][0]) print('Inicio de análisis estático elástico\n\n') ops.start() ops.analyze(20, 5.0e2) print('Fin de análisis estático elástico\n\n') #win.ui.progressBar.setValue(40) # update materials to consider plastic behavior # ============================================================================= ops.updateMaterialStage('-material', int(k + 1), '-stage', 1) # ============================================================================= # plastic gravity loading print('Inicio de análisis estático plástico\n\n') ok = ops.analyze(40, 5.0e-2) if ok != 0: error = 'Error de convergencia en análisis estático de modelo' + str( perfil) + '\n\n' print(error) break print('Fin de análisis estático plástico\n\n') #----------------------------------------------------------------------------------------- # 11. UPDATE ELEMENT PERMEABILITY VALUES FOR POST-GRAVITY ANALYSIS #----------------------------------------------------------------------------------------- ini = 1 aum = 0 sum = 0 for j in range(capas): #Layer 3 ops.setParameter( '-val', permutaciones[i][16][j], ['-eleRange', int(ini + aum), int(nElemY[j] + sum)], 'xPerm') ops.setParameter( '-val', permutaciones[i][17][j], ['-eleRange', int(ini + aum), int(nElemY[j] + sum)], 'yPerm') ops.setParameter( '-val', permutaciones[i][16][j], ['-eleRange', int(ini + aum), int(nElemY[j] + sum)], 'zPerm') ini = nElemY[j] + sum sum += nElemY[j] aum = 1 print("Finished updating permeabilities for dynamic analysis...") # ============================================================================= # ########### Grabadores dinámicos ########## # ============================================================================= ops.setTime(0.0) ops.wipeAnalysis() ops.remove('recorders') # tiempo de la grabadora recDT = 10 * dt path_acel = path + '/Post-proceso/' + perfil + '/dinamico/aceleraciones/' ops.recorder('Node', '-file', path_acel + 'accelerationx.out', '-time', '-dT', recDT, '-node', *nodos, '-dof', 1, 'accel') print('Fin de creación de grabadores\n\n') #win.ui.progressBar.setValue(50) # ============================================================================= # ######### Determinación de análisis dinámico ########## # ============================================================================= # objeto de serie temporal para el historial de fuerza path_vel = path + '/Pre-proceso/' + perfil + '/TREASISL2.txt' ops.timeSeries('Path', 1, '-dt', dt, '-filePath', path_vel, '-factor', dashpotCoeff) ops.pattern('Plain', 10, 1) ops.load(1, *[1.0, 0.0, 0.0, 0.0]) #CAMBIO REALIZADO OJO print('Fin de creación de carga dinámica\n\n') # algoritmo de análisis dinámico ops.constraints(permutaciones[i][39][0], float(permutaciones[i][39][1]), float(permutaciones[i][39][2])) ops.test(permutaciones[i][41][0], float(permutaciones[i][41][1]), int(permutaciones[i][41][2]), int(permutaciones[i][41][3])) ops.algorithm(permutaciones[i][45][0]) ops.numberer(permutaciones[i][40][0]) ops.system(permutaciones[i][43][0]) ops.integrator(permutaciones[i][42][0], float(permutaciones[i][42][1]), float(permutaciones[i][42][2])) ops.analysis(permutaciones[i][44][0]) # ============================================================================= # ops.rayleigh(a0, a1, 0.0, 0.0) # ============================================================================= print('Inicio de análisis dinámico\n\n') #win.ui.progressBar.setValue(85) ok = ops.analyze(nStep, dT) if ok != 0: error = 'Error de convergencia en análisis dinámico de modelo' + str( permutaciones[i][0]) + '\n\n' print(error) curTime = ops.getTime() mTime = curTime print('cursTime:' + str(curTime)) curStep = (curTime / dT) print('cursStep:' + str(curStep)) rStep = (nStep - curStep) * 2.0 remStep = int(nStep - curStep) * 2.0 print('remSTep:' + str(curStep)) dT = (dT / 2) print('dT:' + str(dT)) ops.analyze(remStep, dT) if ok != 0: error = 'Error de convergencia en análisis dinámico de modelo' + str( permutaciones[i][0]) + '\n\n' print(error) curTime = ops.getTime() print('cursTime:' + str(curTime)) curStep = (curTime - mTime) / dT print('cursStep:' + str(curStep)) remStep = int(rStep - curStep) * 2 print('remSTep:' + str(curStep)) dT = (dT / 2) print('dT:' + str(dT)) ops.analyze(remStep, dT) print('Fin de análisis dinámico\n\n') ops.wipe()
for i in range(nNode): ops.node(i+1, *Node[i][1:]) # construccion de elementos for i in range(nEle): if (Ele[i][0] == 1): ops.element('quad', i+1, *Ele[i][2:], B, 'PlaneStress', Ele[i][0]) # condiciones de frontera boundFix(nNode, Node) ops.timeSeries('Linear',1) ops.pattern('Plain',1,1) fx = 0 fy = -10*kN ops.load(2, fx, fy) #for i in range(nNode): # if (Node[i][0] == 2): # ops.load(i+1, fx, fy) ops.system('FullGeneral') # probar otros solvers: 'UmfPack' 'SparseSYM' ops.numberer('Plain') ops.constraints('Plain') ops.integrator('LoadControl',1) ops.algorithm('Linear') ops.analysis('Static') ops.analyze(1) # Desplazamiento disp = ops.nodeDisp(2,2) print(disp)
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")