def PushoverLcD(Nsteps):
    
    ControlNode = 4
    ControlNodeDof = 1
    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.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**-8, 50)
    
    # Run Analysis
    
    op.record()

    ok = op.analyze(Nsteps)
    nn = 0     
Exemple #2
0
def analysis(P, 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')
    
    temp = 1 / steps
    ops.integrator('LoadControl', temp)
    
    ops.analysis('Static')
    
    ops.analyze(steps)
    
    
    ##########################################################################
    
    
    opsplt.plot_model()
    
    
    ##########################################################################
    
    
    ops.wipe()
    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.")
Exemple #4
0
op.recorder('Node', '-file', 'Data-2c/DBase.out','-time', '-node', 1, '-dof', 1,2,3, 'disp')
op.recorder('Node', '-file', 'Data-2c/RBase.out','-time', '-node', 1, '-dof', 1,2,3, 'reaction')
#op.recorder('Drift', '-file', 'Data-2c/Drift.out','-time', '-node', 1, '-dof', 1,2,3, 'disp')
op.recorder('Element', '-file', 'Data-2c/FCol.out','-time', '-ele', 1, 'globalForce')
op.recorder('Element', '-file', 'Data-2c/ForceColSec1.out','-time', '-ele', 1, 'section', 1, 'force')
#op.recorder('Element', '-file', 'Data-2c/DCol.out','-time', '-ele', 1, 'deformations')

#defining gravity loads
op.timeSeries('Linear', 1)
op.pattern('Plain', 1, 1)
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
 
#applying Dynamic Ground motion analysis
GMdirection = 1
GMfile = 'BM68elc.acc'
GMfact = 1.0
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
Exemple #6
0
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]))
Exemple #7
0
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]
Exemple #8
0
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()
    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
Exemple #10
0
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
ops.algorithm('Newton')

# create integrator object
ops.integrator('PFEM')

# create SOE object
ops.system('PFEM', '-umfpack', '-print')

# create analysis object
ops.analysis('PFEM', dtmax, dtmin, b2)

# analysis
while ops.getTime() < totaltime:

    # analysis
    if ops.analyze() < 0:
        break

    ops.remesh(alpha)
Exemple #11
0
def test_EigenAnal_twoStoryFrame1():
    ops.wipe()

    #input
    m = 100.0 / 386.0
    numModes = 2

    #material
    A = 63.41
    I = 320.0
    E = 29000.0

    #geometry
    L = 240.
    h = 120.

    # define the model
    #---------------------------------
    #model builder
    ops.model('BasicBuilder', '-ndm', 2, '-ndf', 3)

    # nodal coordinates:
    ops.node(1, 0., 0.)
    ops.node(2, L, 0.)
    ops.node(3, 0., h)
    ops.node(4, L, h)
    ops.node(5, 0., 2 * h)
    ops.node(6, L, 2 * h)

    # Single point constraints -- Boundary Conditions
    ops.fix(1, 1, 1, 1)
    ops.fix(2, 1, 1, 1)

    # assign mass
    ops.mass(3, m, 0., 0.)
    ops.mass(4, m, 0., 0.)
    ops.mass(5, m / 2., 0., 0.)
    ops.mass(6, m / 2., 0., 0.)

    # define geometric transformation:
    TransfTag = 1
    ops.geomTransf('Linear', TransfTag)

    # define elements:
    # columns
    ops.element('elasticBeamColumn', 1, 1, 3, A, E, 2. * I, TransfTag)
    ops.element('elasticBeamColumn', 2, 3, 5, A, E, I, TransfTag)
    ops.element('elasticBeamColumn', 3, 2, 4, A, E, 2. * I, TransfTag)
    ops.element('elasticBeamColumn', 4, 4, 6, A, E, I, TransfTag)
    # beams
    ops.element('elasticBeamColumn', 5, 3, 4, A, E, 2 * I, TransfTag)
    ops.element('elasticBeamColumn', 6, 5, 6, A, E, I, TransfTag)

    # record eigenvectors
    #----------------------
    # for { k 1 } { k <= numModes } { incr k } {
    #     recorder Node -file format "modes/mode%i.out" k -nodeRange 1 6 -dof 1 2 3  "eigen k"
    # }

    # perform eigen analysis
    #-----------------------------
    lamb = ops.eigen(numModes)

    # calculate frequencies and periods of the structure
    #---------------------------------------------------
    omega = []
    f = []
    T = []
    pi = 3.141593

    for lam in lamb:
        print("labmbda = ", lam)
        omega.append(math.sqrt(lam))
        f.append(math.sqrt(lam) / (2 * pi))
        T.append((2 * pi) / math.sqrt(lam))

    print("periods are ", T)

    # write the output file cosisting of periods
    #--------------------------------------------
    period = "Periods.txt"
    Periods = open(period, "w")
    for t in T:
        Periods.write(repr(t) + '\n')

    Periods.close()

    # create display  for mode shapes
    #---------------------------------
    #                 windowTitle xLoc yLoc xPixels yPixels
    # recorder display "Mode Shape 1"  10    10     500      500     -wipe
    # prp h h 1                                         # projection reference point (prp) defines the center of projection (viewer eye)
    # vup  0  1 0                                         # view-up vector (vup)
    # vpn  0  0 1                                         # view-plane normal (vpn)
    # viewWindow -200 200 -200 200                        # coordiantes of the window relative to prp
    # display -1 5 20
    # the 1st arg. is the tag for display mode (ex. -1 is for the first mode shape)
    # the 2nd arg. is magnification factor for nodes, the 3rd arg. is magnif. factor of deformed shape
    # recorder display "Mode Shape 2" 10 510 500 500 -wipe
    # prp h h 1
    # vup  0  1 0
    # vpn  0  0 1
    # viewWindow -200 200 -200 200
    # display -2 5 20

    # Run a one step gravity load with no loading (to record eigenvectors)
    #-----------------------------------------------------------------------
    ops.integrator('LoadControl', 0.0, 1, 0.0, 0.0)

    # Convergence test
    #                     tolerance maxIter displayCode
    ops.test('EnergyIncr', 1.0e-10, 100, 0)

    # Solution algorithm
    ops.algorithm('Newton')

    # DOF numberer
    ops.numberer('RCM')

    # Constraint handler
    ops.constraints('Transformation')

    # System of equations solver
    ops.system('ProfileSPD')

    ops.analysis('Static')
    res = ops.analyze(1)
    if res < 0:
        print("Modal analysis failed")

    # get values of eigenvectors for translational DOFs
    #---------------------------------------------------
    f11 = ops.nodeEigenvector(3, 1, 1)
    f21 = ops.nodeEigenvector(5, 1, 1)
    f12 = ops.nodeEigenvector(3, 2, 1)
    f22 = ops.nodeEigenvector(5, 2, 1)
    print("eigenvector 1: ", [f11 / f21, f21 / f21])
    print("eigenvector 2: ", [f12 / f22, f22 / f22])

    assert abs(T[0] - 0.628538768190688) < 1e-12 and abs(
        T[1] - 0.2359388635361575) < 1e-12 and abs(
            f11 / f21 - 0.3869004256389493) < 1e-12 and abs(
                f21 / f21 - 1.0) < 1e-12 and abs(f12 / f22 + 1.2923221761110006
                                                 ) < 1e-12 and abs(f22 / f22 -
                                                                   1.0) < 1e-12
Exemple #12
0
def test_PinchedCylinder():

    P = 1
    R = 300.
    L = 600.
    E = 3e6
    thickness = R / 100.

    uExact = -164.24 * P / (E * thickness)

    formatString = '{:>20s}{:>15.5e}'
    print("\n  Displacement Under Applied Load:\n")

    formatString = '{:>20s}{:>10s}{:>15s}{:>15s}{:>15s}'
    print(
        formatString.format("Element Type", "   mesh  ", "OpenSees", "Exact",
                            "%Error"))

    for shellType in ['ShellMITC4', 'ShellDKGQ', 'ShellNLDKGQ']:
        for numEle in [4, 16, 32]:

            ops.wipe()

            # ----------------------------
            # Start of model generation
            # ----------------------------
            ops.model('basic', '-ndm', 3, '-ndf', 6)

            radius = R
            length = L / 2.

            E = 3.0e6
            v = 0.3
            PI = 3.14159

            ops.nDMaterial('ElasticIsotropic', 1, E, v)
            ops.nDMaterial('PlateFiber', 2, 1)
            ops.section('PlateFiber', 1, 2, thickness)
            #section ElasticMembranePlateSection  1   E v thickness 0.
            nR = numEle
            nY = numEle

            tipNode = (nR + 1) * (nY + 1)

            #create nodes
            nodeTag = 1
            for i in range(nR + 1):
                theta = i * PI / (2.0 * nR)
                xLoc = 300 * cos(theta)
                zLoc = 300 * sin(theta)

                for j in range(nY + 1):
                    yLoc = j * length / (1.0 * nY)
                    ops.node(nodeTag, xLoc, yLoc, zLoc)
                    nodeTag += 1

            #create elements
            eleTag = 1
            for i in range(nR):
                iNode = i * (nY + 1) + 1
                jNode = iNode + 1
                lNode = iNode + (nY + 1)
                kNode = lNode + 1
                for j in range(nY):
                    ops.element(shellType, eleTag, iNode, jNode, kNode, lNode,
                                1)
                    eleTag += 1
                    iNode += 1
                    jNode += 1
                    kNode += 1
                    lNode += 1

            # define the boundary conditions
            ops.fixX(radius, 0, 0, 1, 1, 1, 0, '-tol', 1.0e-2)
            ops.fixZ(radius, 1, 0, 0, 0, 1, 1, '-tol', 1.0e-2)
            ops.fixY(0., 1, 0, 1, 0, 0, 0, '-tol', 1.0e-2)
            ops.fixY(length, 0, 1, 0, 1, 0, 1, '-tol', 1.0e-2)

            #define loads
            ops.timeSeries('Linear', 1)
            ops.pattern('Plain', 1, 1)
            ops.load(tipNode, 0., 0., -1. / 4.0, 0., 0., 0.)

            ops.integrator('LoadControl', 1.0)
            ops.test('EnergyIncr', 1.0e-10, 20, 0)
            ops.algorithm('Newton')
            ops.numberer('RCM')
            ops.constraints('Plain')
            ops.system('Umfpack')
            ops.analysis('Static')

            ops.analyze(1)
            res = ops.nodeDisp(tipNode, 3)
            err = abs(100 * (uExact - res) / uExact)
            formatString = '{:>20s}{:>5d}{:>3s}{:>2d}{:>15.5e}{:>15.5e}{:>15.2f}'
            print(
                formatString.format(shellType, numEle, " x ", numEle, res,
                                    uExact, err))

    tol = 5.0
    if abs(100 * (uExact - res) / uExact) > tol:
        testOK = 1
    else:
        testOK = 0

    assert testOK == 0
Exemple #13
0
    ops.node(2, 144.0, 0.0)
    ops.node(3, 168.0, 0.0)
    ops.node(4, 72.0, 96.0)

    ops.fix(2, 1, 1)
    ops.fix(3, 1, 1)

    ops.element('Truss', 2, 2, 4, 5.0, 1)
    ops.element('Truss', 3, 3, 4, 5.0, 1)

ops.constraints('Transformation')
ops.numberer('ParallelPlain')
ops.system('Mumps')
ops.test('NormDispIncr', 1e-6, 6, 2)
ops.algorithm('Newton')
ops.integrator('LoadControl', 0.1)
ops.analysis('Static')

ops.analyze(10)

print('Node 4: ', [ops.nodeCoord(4), ops.nodeDisp(4)])

ops.loadConst('-time', 0.0)

if pid == 0:
    ops.pattern('Plain', 2, 1)
    ops.load(4, 1.0, 0.0)

ops.domainChange()
ops.integrator('ParallelDisplacementControl', 4, 1, 0.1)
ops.analyze(10)
Exemple #14
0
def get_inelastic_response(mass,
                           k_spring,
                           f_yield,
                           motion,
                           dt,
                           xi=0.05,
                           r_post=0.0):
    """
    Run seismic analysis of a nonlinear SDOF

    :param mass: SDOF mass
    :param k_spring: spring stiffness
    :param f_yield: yield strength
    :param motion: list, acceleration values
    :param dt: float, time step of acceleration values
    :param xi: damping ratio
    :param r_post: post-yield stiffness
    :return:
    """

    opy.wipe()
    opy.model('basic', '-ndm', 2, '-ndf', 3)  # 2 dimensions, 3 dof per node

    # Establish nodes
    bot_node = 1
    top_node = 2
    opy.node(bot_node, 0., 0.)
    opy.node(top_node, 0., 0.)

    # Fix bottom node
    opy.fix(top_node, opc.FREE, opc.FIXED, opc.FIXED)
    opy.fix(bot_node, opc.FIXED, opc.FIXED, opc.FIXED)
    # Set out-of-plane DOFs to be slaved
    opy.equalDOF(1, 2, *[2, 3])

    # nodal mass (weight / g):
    opy.mass(top_node, mass, 0., 0.)

    # Define material
    bilinear_mat_tag = 1
    mat_type = "Steel01"
    mat_props = [f_yield, k_spring, r_post]
    opy.uniaxialMaterial(mat_type, bilinear_mat_tag, *mat_props)

    # Assign zero length element
    beam_tag = 1
    opy.element('zeroLength', beam_tag, bot_node, top_node, "-mat",
                bilinear_mat_tag, "-dir", 1, '-doRayleigh', 1)

    # Define the dynamic analysis
    load_tag_dynamic = 1
    pattern_tag_dynamic = 1

    values = list(-1 * motion)  # should be negative
    opy.timeSeries('Path', load_tag_dynamic, '-dt', dt, '-values', *values)
    opy.pattern('UniformExcitation', pattern_tag_dynamic, opc.X, '-accel',
                load_tag_dynamic)

    # set damping based on first eigen mode
    angular_freq2 = opy.eigen('-fullGenLapack', 1)
    if hasattr(angular_freq2, '__len__'):
        angular_freq2 = angular_freq2[0]
    angular_freq = angular_freq2**0.5
    alpha_m = 0.0
    beta_k = 2 * xi / angular_freq
    beta_k_comm = 0.0
    beta_k_init = 0.0

    opy.rayleigh(alpha_m, beta_k, beta_k_init, beta_k_comm)

    # Run the dynamic analysis

    opy.wipeAnalysis()

    opy.algorithm('Newton')
    opy.system('SparseGeneral')
    opy.numberer('RCM')
    opy.constraints('Transformation')
    opy.integrator('Newmark', 0.5, 0.25)
    opy.analysis('Transient')

    tol = 1.0e-10
    iterations = 10
    opy.test('EnergyIncr', tol, iterations, 0, 2)
    analysis_time = (len(values) - 1) * dt
    analysis_dt = 0.001
    outputs = {
        "time": [],
        "rel_disp": [],
        "rel_accel": [],
        "rel_vel": [],
        "force": []
    }

    while opy.getTime() < analysis_time:
        curr_time = opy.getTime()
        opy.analyze(1, analysis_dt)
        outputs["time"].append(curr_time)
        outputs["rel_disp"].append(opy.nodeDisp(top_node, 1))
        outputs["rel_vel"].append(opy.nodeVel(top_node, 1))
        outputs["rel_accel"].append(opy.nodeAccel(top_node, 1))
        opy.reactions()
        outputs["force"].append(
            -opy.nodeReaction(bot_node, 1))  # Negative since diff node
    opy.wipe()
    for item in outputs:
        outputs[item] = np.array(outputs[item])

    return outputs
def test_PlanarTruss():
    A = 10.0
    E = 3000.
    L = 200.0
    alpha = 30.0
    P = 200.0

    sigmaYP = 60.0

    pi = 2.0*asin(1.0)
    alphaRad = alpha*pi/180.
    cosA = cos(alphaRad)
    sinA = sin(alphaRad)

    # EXACT RESULTS per Popov
    F1 = P/(2*cosA*cosA*cosA + 1)
    F2 = F1*cosA*cosA
    disp = -F1*L/(A*E)

    # create the finite element model
    ops.wipe()

    ops.model('Basic', '-ndm', 2, '-ndf', 2)

    dX = L*tan(alphaRad)

    ops.node( 1,    0.0,          0.0)
    ops.node( 2,    dX,          0.0)
    ops.node( 3, 2.0*dX,  0.0)
    ops.node( 4,    dX,         -L     )

    ops.fix( 1, 1, 1)
    ops.fix( 2, 1, 1)
    ops.fix( 3, 1, 1)

    ops.uniaxialMaterial('Elastic', 1, E)
    ops.element('Truss', 1, 1, 4, A, 1)
    ops.element('Truss', 2, 2, 4, A, 1)
    ops.element('Truss', 3, 3, 4, A, 1)

    ops.timeSeries('Linear', 1)
    ops.pattern('Plain', 1, 1)
    ops.load( 4, 0., -P)

    ops.numberer( 'Plain')
    ops.constraints( 'Plain')
    ops.algorithm( 'Linear')
    ops.system('ProfileSPD')
    ops.integrator('LoadControl', 1.0)
    ops.analysis('Static')
    ops.analyze(1)


    # determine PASS/FAILURE of test
    testOK = 0

    #
    # print table of camparsion
    #          

    comparisonResults = F2, F1, F2
    print("\nElement Force Comparison:")
    tol = 1.0e-6
    print('{:>10}{:>15}{:>15}'.format('Element','OpenSees','Popov'))


    for i in range(1,4):
        exactResult = comparisonResults[i-1]
        eleForce = ops.eleResponse(i, 'axialForce')
        print('{:>10d}{:>15.4f}{:>15.4f}'.format(i, eleForce[0], exactResult))
        if abs(eleForce[0]-exactResult) > tol:
            testOK = -1
            print("failed force-> ", abs(eleForce[0]-exactResult), " ", tol)


    print("\nDisplacement Comparison:")
    osDisp = ops.nodeDisp( 4, 2)
    print('{:>10}{:>15.8f}{:>10}{:>15.8f}'.format('OpenSees:',osDisp,'Exact:', disp))
    if abs(osDisp-disp) > tol:
        testOK = -1
        print("failed linear disp")



    print("\n\n  - NonLinear (Example2.23)")

    #EXACT
    # Exact per Popov

    PA = (sigmaYP*A) * (1.0+2*cosA*cosA*cosA)
    dispA = PA/P*disp

    PB = (sigmaYP*A) * (1.0+2*cosA)
    dispB = dispA / (cosA*cosA)

    # create the new finite element model for nonlinear case
    #   will apply failure loads and calculate displacements

    ops.wipe()

    ops.model('Basic', '-ndm', 2, '-ndf', 2)

    ops.node( 1,    0.0,          0.0)
    ops.node( 2,    dX,          0.0)
    ops.node( 3, 2.0*dX,  0.0)
    ops.node( 4,    dX,         -L     )

    ops.fix( 1, 1, 1)
    ops.fix( 2, 1, 1)
    ops.fix( 3, 1, 1)

    ops.uniaxialMaterial( 'ElasticPP', 1, E, sigmaYP/E)
    ops.element('Truss', 1, 1, 4, A, 1)
    ops.element('Truss', 2, 2, 4, A, 1)
    ops.element('Truss', 3, 3, 4, A, 1)

    ops.timeSeries( 'Path', 1, '-dt', 1.0, '-values', 0.0, PA, PB, PB)
    ops.pattern('Plain', 1, 1)
    ops.load( 4, 0., -1.0)

    ops.numberer('Plain')
    ops.constraints('Plain')
    ops.algorithm('Linear')
    ops.system('ProfileSPD')
    ops.integrator('LoadControl', 1.0)
    ops.analysis('Static')
    ops.analyze(1)

    osDispA = ops.nodeDisp( 4, 2)
    #print node 4
    #print ele

    ops.analyze(1)
    osDispB = ops.nodeDisp( 4, 2)

    #print node 4
    #print ele


    # determine PASS/FAILURE of test
    testOK = 0

    print("\nDisplacement Comparison:")
    print("elastic limit state:")
    osDisp = ops.nodeDisp( 4, 2)
    print('{:>10}{:>15.8f}{:>10}{:>15.8f}'.format('OpenSees:',osDispA,'Exact:',dispA))
    if abs(osDispA-dispA) > tol:
        testOK = -1
        print("failed nonlineaer elastic limit disp")

    print("collapse limit state:")
    print('{:>10}{:>15.8f}{:>10}{:>15.8f}'.format('OpenSees:',osDispB,'Exact:',dispB))
    if abs(osDispB-dispB) > tol:
        testOK = -1
        print("failed nonlineaer collapse limit disp")

    assert testOK == 0
Exemple #16
0
Hload = Weight
maxNumIter = 6
tol = 1e-8

op.timeSeries('Linear', 2)
op.pattern('Plain', 200, 2)
op.load(2, Hload, 0.0, 0.0)

op.wipeAnalysis()
op.constraints('Plain')
op.numberer('Plain')
op.system('BandGeneral')
op.test('EnergyIncr', Tol, maxNumIter)
op.algorithm('Newton')

op.integrator('DisplacementControl', IDctrlNode, IDctrlDOF, Dincr)
op.analysis('Static')

Nsteps = int(Dmax / Dincr)

ok = op.analyze(Nsteps)
print(ok)

# for gravity analysis, load control is fine, 0.1 is the load factor increment (http://opensees.berkeley.edu/wiki/index.php/Load_Control)

test = {
    1: 'NormDispIncr',
    2: 'RelativeEnergyIncr',
    4: 'RelativeNormUnbalance',
    5: 'RelativeNormDispIncr',
    6: 'NormUnbalance'
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)
Exemple #18
0
def test_PortalFrame2d():

    # set some properties
    print("================================================")
    print("PortalFrame2d.py: Verification 2d Elastic Frame")
    print("  - eigenvalue and static pushover analysis")

    ops.wipe()

    ops.model('Basic', '-ndm', 2)

    # properties

    #    units kip, ft

    numBay = 2
    numFloor = 7

    bayWidth = 360.0
    storyHeights = [162.0, 162.0, 156.0, 156.0, 156.0, 156.0, 156.0]

    E = 29500.0
    massX = 0.49
    M = 0.
    coordTransf = "Linear"  # Linear, PDelta, Corotational
    massType = "-lMass"  # -lMass, -cMass

    beams = [
        'W24X160', 'W24X160', 'W24X130', 'W24X130', 'W24X110', 'W24X110',
        'W24X110'
    ]
    eColumn = [
        'W14X246', 'W14X246', 'W14X246', 'W14X211', 'W14X211', 'W14X176',
        'W14X176'
    ]
    iColumn = [
        'W14X287', 'W14X287', 'W14X287', 'W14X246', 'W14X246', 'W14X211',
        'W14X211'
    ]
    columns = [eColumn, iColumn, eColumn]

    WSection = {
        'W14X176': [51.7, 2150.],
        'W14X211': [62.1, 2670.],
        'W14X246': [72.3, 3230.],
        'W14X287': [84.4, 3910.],
        'W24X110': [32.5, 3330.],
        'W24X130': [38.3, 4020.],
        'W24X160': [47.1, 5120.]
    }

    nodeTag = 1

    # procedure to read
    def ElasticBeamColumn(eleTag, iNode, jNode, sectType, E, transfTag, M,
                          massType):

        found = 0

        prop = WSection[sectType]

        A = prop[0]
        I = prop[1]
        ops.element('elasticBeamColumn', eleTag, iNode, jNode, A, E, I,
                    transfTag, '-mass', M, massType)

    # add the nodes
    #  - floor at a time
    yLoc = 0.
    for j in range(0, numFloor + 1):

        xLoc = 0.
        for i in range(0, numBay + 1):
            ops.node(nodeTag, xLoc, yLoc)
            xLoc += bayWidth
            nodeTag += 1

        if j < numFloor:
            storyHeight = storyHeights[j]

        yLoc += storyHeight

    # fix first floor
    ops.fix(1, 1, 1, 1)
    ops.fix(2, 1, 1, 1)
    ops.fix(3, 1, 1, 1)

    #rigid floor constraint & masses
    nodeTagR = 5
    nodeTag = 4
    for j in range(1, numFloor + 1):
        for i in range(0, numBay + 1):

            if nodeTag != nodeTagR:
                ops.equalDOF(nodeTagR, nodeTag, 1)
            else:
                ops.mass(nodeTagR, massX, 1.0e-10, 1.0e-10)

            nodeTag += 1

        nodeTagR += numBay + 1

    # add the columns
    # add column element
    ops.geomTransf(coordTransf, 1)
    eleTag = 1
    for j in range(0, numBay + 1):

        end1 = j + 1
        end2 = end1 + numBay + 1
        thisColumn = columns[j]

        for i in range(0, numFloor):
            secType = thisColumn[i]
            ElasticBeamColumn(eleTag, end1, end2, secType, E, 1, M, massType)
            end1 = end2
            end2 += numBay + 1
            eleTag += 1

    # add beam elements
    for j in range(1, numFloor + 1):
        end1 = (numBay + 1) * j + 1
        end2 = end1 + 1
        secType = beams[j - 1]
        for i in range(0, numBay):
            ElasticBeamColumn(eleTag, end1, end2, secType, E, 1, M, massType)
            end1 = end2
            end2 = end1 + 1
            eleTag += 1

    # calculate eigenvalues & print results
    numEigen = 7
    eigenValues = ops.eigen(numEigen)
    PI = 2 * asin(1.0)

    #
    # apply loads for static analysis & perform analysis
    #

    ops.timeSeries('Linear', 1)
    ops.pattern('Plain', 1, 1)
    ops.load(22, 20.0, 0., 0.)
    ops.load(19, 15.0, 0., 0.)
    ops.load(16, 12.5, 0., 0.)
    ops.load(13, 10.0, 0., 0.)
    ops.load(10, 7.5, 0., 0.)
    ops.load(7, 5.0, 0., 0.)
    ops.load(4, 2.5, 0., 0.)

    ops.integrator('LoadControl', 1.0)
    ops.algorithm('Linear')
    ops.analysis('Static')
    ops.analyze(1)

    # determine PASS/FAILURE of test
    ok = 0

    #
    # print pretty output of comparsions
    #

    #               SAP2000   SeismoStruct
    comparisonResults = [[
        1.2732, 0.4313, 0.2420, 0.1602, 0.1190, 0.0951, 0.0795
    ], [1.2732, 0.4313, 0.2420, 0.1602, 0.1190, 0.0951, 0.0795]]
    print("\n\nPeriod Comparisons:")
    print('{:>10}{:>15}{:>15}{:>15}'.format('Period', 'OpenSees', 'SAP2000',
                                            'SeismoStruct'))

    #formatString {%10s%15.5f%15.4f%15.4f}
    for i in range(0, numEigen):
        lamb = eigenValues[i]
        period = 2 * PI / sqrt(lamb)
        print('{:>10}{:>15.5f}{:>15.4f}{:>15.4f}'.format(
            i + 1, period, comparisonResults[0][i], comparisonResults[1][i]))
        resultOther = comparisonResults[0][i]
        if abs(period - resultOther) > 9.99e-5:
            ok = -1

    # print table of camparsion
    #       Parameter          SAP2000   SeismoStruct
    comparisonResults = [[
        "Disp Top", "Axial Force Bottom Left", "Moment Bottom Left"
    ], [1.45076, 69.99, 2324.68], [1.451, 70.01, 2324.71]]
    tolerances = [9.99e-6, 9.99e-3, 9.99e-3]

    print("\n\nSatic Analysis Result Comparisons:")
    print('{:>30}{:>15}{:>15}{:>15}'.format('Parameter', 'OpenSees', 'SAP2000',
                                            'SeismoStruct'))
    for i in range(3):
        response = ops.eleResponse(1, 'forces')
        if i == 0:
            result = ops.nodeDisp(22, 1)
        elif i == 1:
            result = abs(response[1])
        else:
            result = response[2]

        print('{:>30}{:>15.3f}{:>15.2f}{:>15.2f}'.format(
            comparisonResults[0][i], result, comparisonResults[1][i],
            comparisonResults[2][i]))
        resultOther = comparisonResults[1][i]
        tol = tolerances[i]
        if abs(result - resultOther) > tol:
            ok = -1
            print("failed-> ", i, abs(result - resultOther), tol)

    assert ok == 0
Exemple #19
0
         *wallnodes)

# 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-5, 1e-5, 10, 3, 1, 2)

# create algorithm object
ops.algorithm('Newton')

# create integrator object
ops.integrator('PFEM', 0.5, 0.25)

# create SOE object
ops.system('PFEM')
# ops.system('PFEM', '-mumps) Linux version can use mumps

# create analysis object
ops.analysis('PFEM', dtmax, dtmin, b2)

# analysis
while ops.getTime() < totaltime:

    # analysis
    if ops.analyze() < 0:
        break
Exemple #20
0
def run_sensitivity_analysis(ctrlNode,
                             dof,
                             baseNode,
                             SensParam,
                             steps=500,
                             IOflag=False):
    """
    Run load-control sensitivity analysis
    """
    ops.wipeAnalysis()
    start_time = time.time()

    title("Running Load-Control Sensitivity Analysis ...")

    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.sensitivityAlgorithm(
        "-computeAtEachStep"
    )  # automatically compute sensitivity at the end of each step

    outputs = {
        "time": np.array([]),
        "disp": np.array([]),
        "force": np.array([]),
    }

    for sens in SensParam:
        outputs[f"sensDisp_{sens}"] = np.array([]),

    for i in range(steps):
        ops.reactions()
        if IOflag:
            print(
                f"Single Cycle Response: Step #{i}, Node #{ctrlNode}: {ops.nodeDisp(ctrlNode, dof):.3f} {LunitTXT} / {-ops.nodeReaction(baseNode, dof):.2f} {FunitTXT}."
            )
        ops.analyze(1)
        tCurrent = ops.getTime()

        outputs["time"] = np.append(outputs["time"], tCurrent)
        outputs["disp"] = np.append(outputs["disp"],
                                    ops.nodeDisp(ctrlNode, dof))
        outputs["force"] = np.append(outputs["force"],
                                     -ops.nodeReaction(baseNode, dof))

        for sens in SensParam:
            # sensDisp(patternTag, paramTag)
            outputs[f"sensDisp_{sens}"] = np.append(
                outputs[f"sensDisp_{sens}"],
                ops.sensNodeDisp(ctrlNode, dof, sens))

    title("Sensitvity Analysis Completed!")
    print(
        f"Analysis elapsed time is {(time.time() - start_time):.3f} seconds.\n"
    )

    return outputs
def Analysis_Proc(Num: int, Node: int, dof: int, Dincr: float):
    '''
      brief KrylovNewton → Newton -SecantNewton → ModifiedNewton → NewtonWithLineSearch → BGFS → Broyden\n
      pararm Num the number of analyze step\n
      return analyze if successful return 0
      if NOT successful return < 0\n
    '''
    for step in range(1, Num + 1):
        logger.info("No. %d of Cyclic. Anaylsis KrylovNewton..", step)
        ops.algorithm('KrylovNewton')
        ops.integrator("DisplacementControl", Node, dof, Dincr)
        ops.analysis("Static")
        ok = ops.analyze(1)

        if ok != 0:
            logger.info("No. %d of Cyclic. Anaylsis Trying SecantNewton ..",
                        step)
            ops.algorithm('SecantNewton')
            ops.integrator("DisplacementControl", Node, dof, Dincr)
            ops.analysis("Static")
            ok = ops.analyze(1)

        if ok != 0:
            logger.info(
                "NO. %d of Cyclic. Anaylsis Trying NewtonLineSearch ..", step)
            ops.algorithm('NewtonLineSearch', True, False, True, False, 0.8,
                          1000, 0.1, 10.0)
            ops.integrator("DisplacementControl", Node, dof, Dincr)
            ops.analysis("Static")
            ok = ops.analyze(1)

        if ok != 0:
            logger.info("No. %d of Cyclic. Anaylsis Trying PeriodicNewton ..",
                        step)
            ops.algorithm('PeriodicNewton')
            ops.integrator("DisplacementControl", Node, dof, Dincr)
            ops.analysis("Static")
            ok = ops.analyze(1)

        if ok != 0:
            logger.info(
                "NO. %d of Cyclic. Anaylsis Trying NewtonWithLineSearch ..",
                step)
            ops.algorithm('NewtonLineSearch')
            ops.integrator("DisplacementControl", Node, dof, Dincr)
            ops.analysis("Static")
            ok = ops.analyze(1)

        if ok != 0:
            logger.info("No. %d of Cyclic. Anaylsis Trying BFGS ..", step)
            ops.algorithm('BFGS', True, False, 10000000)
            ops.integrator("DisplacementControl", Node, dof, Dincr)
            ops.analysis("Static")
            ok = ops.analyze(1)

        if ok != 0:
            logger.info("No. %d of Cyclic. Anaylsis Trying Broyden ..", step)
            ops.algorithm('Broyden')
            ops.integrator("DisplacementControl", Node, dof, Dincr)
            ops.analysis("Static")
            ok = ops.analyze(1)

        if ok != 0:
            logger.info("No. $step of Cyclic. Analysis Convergence Failure!")
# ****************************************************************************
# GRAVITY ANALYSIS EXCECUTED ACCOUNING FOR LIVE, DEAD AND SUPERDEAD LOADS.
# ========================================================================
OPSDMOD.DeadLoadGen(NbaysX[0], NbaysZ, NStr[0], XBDims, ZBDims, ColDims,
                    gamma_conc)
OPSDMOD.SuperDeadLoadGen(NbaysX[0], NbaysZ, NStr[0], XbayL, ZbayL, Qsd)
OPSDMOD.LiveLoadGen(NbaysX[0], NbaysZ, NStr[0], XbayL, ZbayL, Ql, 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[0] + 1) * (NbaysZ + 1)):
    if flex in ('Y', 'YES', 'Yes', 'yES', 'yes', 'y'):
        YReact += ops.nodeReaction(99000 + i + 1, 2)
    else:
        YReact += ops.nodeReaction(i + 1, 2)
print('>>> Gravity loads applied...')

# ==========================================================================
# MODAL ANALYSIS FOR DETERMINING FUNDAMENTAL PERIOD AND ITS DIRECTION.
Exemple #23
0
tf = 0.2 * s
fr = 10 * Hz
prd = 1 / fr
ops.timeSeries('Trig', 1, ti, tf, prd)
# https://openseespydoc.readthedocs.io/en/latest/src/pathTs.html
ops.pattern('UniformExcitation', 1, 1, '-accel', 1)
# https://openseespydoc.readthedocs.io/en/latest/src/uniformExcitation.html

# amortiguamiento de rayleigh
ops.rayleigh(*setRayParam(0.05, 0.05, 0.2, 20))

# analysis commands
ops.constraints('Plain')
ops.numberer('Plain')
ops.system('UmfPack')
ops.algorithm('Linear')
ops.integrator('Newmark', 0.5, 0.25)
ops.analysis('Transient')

# analisis
# ops.analyze(400,0.001)
ops.start()
for i in range(400):
    ops.analyze(1, 0.001)
    print(i)
ops.stop()

# Grafico de la deformada
fig = plt.figure(figsize=(25, 5))
opsv.plot_defo(500)
plt.show()
Exemple #24
0
dt = 0.01  # time step for input ground motion
GMfatt = 1.0  # data in input file is in g Unifts -- ACCELERATION TH
maxNumIter = 10
op.timeSeries('Path', 2, '-dt', dt, '-filePath', GMfile, '-factor', GMfact)
op.pattern('UniformExcitation', IDloadTag, GMdirection, '-accel', 2)

op.wipeAnalysis()
op.constraints('Transformation')
op.numberer('Plain')
op.system('BandGeneral')
op.test('EnergyIncr', Tol, maxNumIter)
op.algorithm('ModifiedNewton')

NewmarkGamma = 0.5
NewmarkBeta = 0.25
op.integrator('Newmark', NewmarkGamma, NewmarkBeta)
op.analysis('Transient')

DtAnalysis = 0.01  # time-step Dt for lateral analysis
TmaxAnalysis = 10.0  # maximum duration of ground-motion analysis

Nsteps = int(TmaxAnalysis / DtAnalysis)

ok = op.analyze(Nsteps, DtAnalysis)

tCurrent = op.getTime()

# for gravity analysis, load control is fine, 0.1 is the load factor increment (http://opensees.berkeley.edu/wiki/index.php/Load_Control)

test = {
    1: 'NormDispIncr',
Exemple #25
0
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
Exemple #26
0
def test_ElasticFrame():
    #
    # some parameter
    #
    PI = 2.0 * asin(1.0)
    g = 386.4
    ft = 12.0
    Load1 = 1185.0
    Load2 = 1185.0
    Load3 = 970.0

    # floor masses
    m1 = Load1 / (4 * g)  # 4 nodes per floor
    m2 = Load2 / (4 * g)
    m3 = Load3 / (4 * g)

    # floor distributed loads
    w1 = Load1 / (90 * ft)  # frame 90 ft long
    w2 = Load2 / (90 * ft)
    w3 = Load3 / (90 * ft)

    # ------------------------------
    # Start of model generation
    # ------------------------------

    # Remove existing model
    ops.wipe()

    # Create ModelBuilder (with two-dimensions and 2 DOF/node)
    ops.model('BasicBuilder', '-ndm', 2, '-ndf', 3)

    # Create nodes
    # ------------

    # Create nodes & add to Domain - command: node nodeId xCrd yCrd <-mass massX massY massRz>
    # NOTE: mass in optional
    ops.node(1, 0.0, 0.0)
    ops.node(2, 360.0, 0.0)
    ops.node(3, 720.0, 0.0)
    ops.node(4, 1080.0, 0.0)
    ops.node(5, 0.0, 162.0, '-mass', m1, m1, 0.0)
    ops.node(6, 360.0, 162.0, '-mass', m1, m1, 0.0)
    ops.node(7, 720.0, 162.0, '-mass', m1, m1, 0.0)
    ops.node(8, 1080.0, 162.0, '-mass', m1, m1, 0.0)
    ops.node(9, 0.0, 324.0, '-mass', m2, m2, 0.0)
    ops.node(10, 360.0, 324.0, '-mass', m2, m2, 0.0)
    ops.node(11, 720.0, 324.0, '-mass', m2, m2, 0.0)
    ops.node(12, 1080.0, 324.0, '-mass', m2, m2, 0.0)
    ops.node(13, 0.0, 486.0, '-mass', m3, m3, 0.0)
    ops.node(14, 360.0, 486.0, '-mass', m3, m3, 0.0)
    ops.node(15, 720.0, 486.0, '-mass', m3, m3, 0.0)
    ops.node(16, 1080.0, 486.0, '-mass', m3, m3, 0.0)

    # the boundary conditions - command: fix nodeID xResrnt? yRestrnt? rZRestrnt?
    ops.fix(1, 1, 1, 1)
    ops.fix(2, 1, 1, 1)
    ops.fix(3, 1, 1, 1)
    ops.fix(4, 1, 1, 1)

    # Define geometric transformations for beam-column elements
    ops.geomTransf('Linear', 1)  # beams
    ops.geomTransf('PDelta', 2)  # columns

    # Define elements
    # Create elastic beam-column - command: element elasticBeamColumn eleID node1 node2 A E Iz geomTransfTag

    # Define the Columns
    ops.element('elasticBeamColumn', 1, 1, 5, 75.6, 29000.0, 3400.0,
                2)  # W14X257
    ops.element('elasticBeamColumn', 2, 5, 9, 75.6, 29000.0, 3400.0,
                2)  # W14X257
    ops.element('elasticBeamColumn', 3, 9, 13, 75.6, 29000.0, 3400.0,
                2)  # W14X257
    ops.element('elasticBeamColumn', 4, 2, 6, 91.4, 29000.0, 4330.0,
                2)  # W14X311
    ops.element('elasticBeamColumn', 5, 6, 10, 91.4, 29000.0, 4330.0,
                2)  # W14X311
    ops.element('elasticBeamColumn', 6, 10, 14, 91.4, 29000.0, 4330.0,
                2)  # W14X311
    ops.element('elasticBeamColumn', 7, 3, 7, 91.4, 29000.0, 4330.0,
                2)  # W14X311
    ops.element('elasticBeamColumn', 8, 7, 11, 91.4, 29000.0, 4330.0,
                2)  # W14X311
    ops.element('elasticBeamColumn', 9, 11, 15, 91.4, 29000.0, 4330.0,
                2)  # W14X311
    ops.element('elasticBeamColumn', 10, 4, 8, 75.6, 29000.0, 3400.0,
                2)  # W14X257
    ops.element('elasticBeamColumn', 11, 8, 12, 75.6, 29000.0, 3400.0,
                2)  # W14X257
    ops.element('elasticBeamColumn', 12, 12, 16, 75.6, 29000.0, 3400.0,
                2)  # W14X257

    # Define the Beams
    ops.element('elasticBeamColumn', 13, 5, 6, 34.7, 29000.0, 5900.0,
                1)  # W33X118
    ops.element('elasticBeamColumn', 14, 6, 7, 34.7, 29000.0, 5900.0,
                1)  # W33X118
    ops.element('elasticBeamColumn', 15, 7, 8, 34.7, 29000.0, 5900.0,
                1)  # W33X118
    ops.element('elasticBeamColumn', 16, 9, 10, 34.2, 29000.0, 4930.0,
                1)  # W30X116
    ops.element('elasticBeamColumn', 17, 10, 11, 34.2, 29000.0, 4930.0,
                1)  # W30X116
    ops.element('elasticBeamColumn', 18, 11, 12, 34.2, 29000.0, 4930.0,
                1)  # W30X116
    ops.element('elasticBeamColumn', 19, 13, 14, 20.1, 29000.0, 1830.0,
                1)  # W24X68
    ops.element('elasticBeamColumn', 20, 14, 15, 20.1, 29000.0, 1830.0,
                1)  # W24X68
    ops.element('elasticBeamColumn', 21, 15, 16, 20.1, 29000.0, 1830.0,
                1)  # W24X68

    # Define loads for Gravity Analysis
    # ---------------------------------

    #create a Linear TimeSeries (load factor varies linearly with time): command timeSeries Linear tag
    ops.timeSeries('Linear', 1)

    # Create a Plain load pattern with a linear TimeSeries:
    #  command pattern Plain tag timeSeriesTag { loads }
    ops.pattern('Plain', 1, 1)
    ops.eleLoad('-ele', 13, 14, 15, '-type', '-beamUniform', -w1)
    ops.eleLoad('-ele', 16, 17, 18, '-type', '-beamUniform', -w2)
    ops.eleLoad('-ele', 19, 20, 21, '-type', '-beamUniform', -w3)

    # ---------------------------------
    # Create Analysis for Gravity Loads
    # ---------------------------------

    # Create the system of equation, a SPD using a band storage scheme
    ops.system('BandSPD')

    # Create the DOF numberer, the reverse Cuthill-McKee algorithm
    ops.numberer('RCM')

    # Create the constraint handler, a Plain handler is used as h**o constraints
    ops.constraints('Plain')

    # Create the integration scheme, the LoadControl scheme using steps of 1.0
    ops.integrator('LoadControl', 1.0)

    # Create the solution algorithm, a Linear algorithm is created
    ops.test('NormDispIncr', 1.0e-10, 6)
    ops.algorithm('Newton')

    # create the analysis object
    ops.analysis('Static')

    # ---------------------------------
    # Perform Gravity Analysis
    # ---------------------------------

    ops.analyze(1)
    # print "node 5: nodeDisp 5"
    # print "node 6: nodeDisp 6"
    # print "node 7: nodeDisp 7"
    # print "node 8: nodeDisp 8"
    # print "node 9: nodeDisp 9"
    # print "node 10: nodeDisp 10"
    # ---------------------------------
    # Check Equilibrium
    # ---------------------------------

    # invoke command to determine nodal reactions
    ops.reactions()

    node1Rxn = ops.nodeReaction(
        1
    )  # nodeReaction command returns nodal reactions for specified node in a list
    node2Rxn = ops.nodeReaction(2)
    node3Rxn = ops.nodeReaction(3)
    node4Rxn = ops.nodeReaction(4)

    inputedFy = -Load1 - Load2 - Load3  # loads added negative Fy diren to ele
    computedFx = node1Rxn[0] + node2Rxn[0] + node3Rxn[0] + node4Rxn[0]
    computedFy = node1Rxn[1] + node2Rxn[1] + node3Rxn[1] + node4Rxn[1]

    print("\nEqilibrium Check After Gravity:")
    print("SumX: Inputed: 0.0 + Computed:", computedFx, " =  ",
          0.0 + computedFx)
    print("SumY: Inputed: ", inputedFy, " + Computed: ", computedFy, " =  ",
          inputedFy + computedFy)

    # ---------------------------------
    # Lateral Load
    # ---------------------------------

    # gravity loads constant and time in domain to e 0.0
    ops.loadConst('-time', 0.0)

    ops.timeSeries('Linear', 2)
    ops.pattern('Plain', 2, 2)
    ops.load(13, 220.0, 0.0, 0.0)
    ops.load(9, 180.0, 0.0, 0.0)
    ops.load(5, 90.0, 0.0, 0.0)

    # ---------------------------------
    # Create Recorder
    # ---------------------------------

    #recorder Element -file EleForces.out -ele 1 4 7 10 forces

    # ---------------------------------
    # Perform Lateral Analysis
    # ---------------------------------

    ops.analyze(1)
    # print "node 5: nodeDisp 5"
    # print "node 6: nodeDisp 6"
    # print "node 7: nodeDisp 7"
    # print "node 8: nodeDisp 8"
    # print "node 9: nodeDisp 9"
    # print "node 10: nodeDisp 10"
    # ---------------------------------
    # Check Equilibrium
    # ---------------------------------

    ops.reactions()

    node1Rxn = ops.nodeReaction(
        1
    )  # =nodeReaction( command returns nodal reactions for specified node in a list
    node2Rxn = ops.nodeReaction(2)
    node3Rxn = ops.nodeReaction(3)
    node4Rxn = ops.nodeReaction(4)

    inputedFx = 220.0 + 180.0 + 90.0
    computedFx = node1Rxn[0] + node2Rxn[0] + node3Rxn[0] + node4Rxn[0]
    computedFy = node1Rxn[1] + node2Rxn[1] + node3Rxn[1] + node4Rxn[1]

    print("\nEqilibrium Check After Lateral Loads:")
    print("SumX: Inputed: ", inputedFx, " + Computed: ", computedFx, " =  ",
          inputedFx + computedFx)
    print("SumY: Inputed: ", inputedFy, " + Computed: ", computedFy, " =  ",
          inputedFy + computedFy)

    # print ele information for columns at base
    #print ele 1 4 7 10

    # ---------------------------------
    # Check Eigenvalues
    # ---------------------------------

    eigenValues = ops.eigen(5)

    print("\nEigenvalues:")
    eigenValue = eigenValues[0]
    T1 = 2 * PI / sqrt(eigenValue)
    print("T1 = ", T1)

    eigenValue = eigenValues[1]
    T2 = 2 * PI / sqrt(eigenValue)
    print("T2 = ", T2)

    eigenValue = eigenValues[2]
    T3 = 2 * PI / sqrt(eigenValue)
    print("T3 = ", T3)

    eigenValue = eigenValues[3]
    T4 = 2 * PI / sqrt(eigenValue)
    print("T4 = ", T4)

    eigenValue = eigenValues[4]
    T5 = 2 * PI / sqrt(eigenValue)
    print("T5 = ", T5)

    assert abs(T1 - 1.0401120938612862) < 1e-12 and abs(
        T2 - 0.3526488583606463
    ) < 1e-12 and abs(T3 - 0.1930409642350476) < 1e-12 and abs(
        T4 - 0.15628823050715784) < 1e-12 and abs(T5 -
                                                  0.13080166151268388) < 1e-12

    #recorder Node -file eigenvector.out -nodeRange 5 16 -dof 1 2 3 eigen 0
    #record

    print("==========================")
Exemple #27
0
op.recorder('Element', '-file', 'Data-4-inelasticFiber/DefoColSec1.out',
            '-time', '-ele', 1, 2, 'section', 1, 'deformation')
#op.recorder('Element', '-file', 'Data-4-inelasticFiber/DCol.out','-time', '-ele', 1, 'deformations')

#defining gravity loads
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
Exemple #28
0
def test_Truss():

    # remove existing model
    ops.wipe()

    # set modelbuilder
    ops.model('basic', '-ndm', 2, '-ndf', 2)

    # create nodes
    ops.node(1, 0.0, 0.0)
    ops.node(2, 144.0, 0.0)
    ops.node(3, 168.0, 0.0)
    ops.node(4, 72.0, 96.0)

    # set boundary condition
    ops.fix(1, 1, 1)
    ops.fix(2, 1, 1)
    ops.fix(3, 1, 1)

    # define materials
    ops.uniaxialMaterial("Elastic", 1, 3000.0)

    # define elements
    ops.element("Truss", 1, 1, 4, 10.0, 1)
    ops.element("Truss", 2, 2, 4, 5.0, 1)
    ops.element("Truss", 3, 3, 4, 5.0, 1)

    # create TimeSeries
    ops.timeSeries("Linear", 1)

    # create a plain load pattern
    ops.pattern("Plain", 1, 1)

    # Create the nodal load - command: load nodeID xForce yForce
    ops.load(4, 100.0, -50.0)

    # ------------------------------
    # Start of analysis generation
    # ------------------------------

    # create SOE
    ops.system("BandSPD")

    # create DOF number
    ops.numberer("Plain")

    # create constraint handler
    ops.constraints("Plain")

    # create integrator
    ops.integrator("LoadControl", 1.0)

    # create algorithm
    ops.algorithm("Linear")

    # create analysis object
    ops.analysis("Static")

    # perform the analysis
    ops.analyze(1)

    ux = ops.nodeDisp(4, 1)
    uy = ops.nodeDisp(4, 2)

    assert abs(ux - 0.53009277713228375450) < 1e-12 and abs(
        uy + 0.17789363846931768864) < 1e-12
Exemple #29
0
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)
Exemple #30
0
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")